Pushing Boxes(广度优先搜索)
首先说明我这个代码和lyd的有点不同:可能更加复杂
既然要求以箱子步数为第一关键字,人的步数为第二关键字,那么我们可以想先找到箱子的最短路径。但单单找到箱子的最短路肯定不行啊,因为有时候不能被推动,怎样确定一条既满足最短又满足可行的箱子路径呢,其实这就是一种有限制的BFS。
对于箱子:
设现在的位置为x,y,扩展方向为dx,dy,将要到达的下一个位置为x+dx,y+dy
check它是否可行:
1.不越界。
2.之前没有走过。
3.不能走到“#”上。
4.人能够从当前站立的位置到达(x-dx,y-dy)。
诶,对了,第4个条件实际上就是对于人的bfs。
因此,这就是一个双重bfs。(数据范围r,c<=20可行!)
那么对于人的bfs,有什么限制条件:当然最重要的不能走到箱子现在的位置(x,y)上
还有记录路径,每次回溯和逆推。
嗯,具体细节看代码吧(不想打字了)
//Pushing Boxes -POJ1475
//最长代码 祭 AC 329ms
//开始没有数组清零WA
//然后数组开大了,TLE
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<queue>
#define de system("pause");
#define re register int
using namespace std;
int r,c,ans,ansx,ansy;
char s[][];
int per[],box[];
int dx[]={-,,,};
int dy[]={,,-,};
char ren[]={'n','s','w','e'};
char xiang[]={'N','S','W','E'};
bool bz[][],flag[][];
struct node{
int x,y,step;
int man[];
node(int xx,int yy,int stepp,int mx,int my)
{
x=xx,y=yy,step=stepp;
man[]=mx,man[]=my;
}
};
struct node2{
int x,y;
node2(int xx,int yy)
{
x=xx;
y=yy;
}
};
queue<node> q;
queue<node2> p;
struct hp{
int px,py,d;
int cnt;
int path[];
}fix[][],walk[][];
//fix主要记录箱子的路径,walk主要记录人的路径。
inline bool bfs(int bx,int by,int aimx,int aimy,int nowx,int nowy)
{
memset(flag,,sizeof flag);
memset(walk,,sizeof walk);
while(p.size()) p.pop();
p.push(node2(nowx,nowy));
if(nowx==aimx&&nowy==aimy) return ;
flag[nowx][nowy]=;
while(!p.empty())
{
node2 now=p.front();
int x=now.x,y=now.y;
p.pop();
for(re i=;i<=;++i)
{
int cx=x+dx[i],cy=y+dy[i];
if(cx<||cx>r||cy<||cy>c)continue;
if(flag[cx][cy])continue;
if(s[cx][cy]=='#')continue;
if(cx==bx&&cy==by)continue;
p.push(node2(cx,cy));
flag[cx][cy]=;
walk[cx][cy].px=x;
walk[cx][cy].py=y;
walk[cx][cy].d=i;
if(cx==aimx&&cy==aimy)
{
return ;
}
}
}
return ;
}
inline bool check(int x,int t1,int y,int t2,int standx,int standy)
{
if(x+t1<||x+t1>r||y+t2<||y+t2>c)return ;
if(bz[x+t1][y+t2]) return ;
if(s[x+t1][y+t2]=='#')return ;
if(bfs(x,y,x-t1,y-t2,standx,standy))//如果人能够移动
{
int tx=x-t1,ty=y-t2;//从目标回溯到初位置
while(tx!=standx||ty!=standy)
{
hp temp=walk[tx][ty];
fix[x+t1][y+t2].path[++fix[x+t1][y+t2].cnt]=walk[tx][ty].d;
tx=temp.px;
ty=temp.py;
}//在这里顺便就把这一次转移路径记录下来
return ;
}
return ;
}
inline void Bfs()
{
while(!q.empty())
{
node now=q.front();
int x=now.x,y=now.y,step=now.step;
int man_x=now.man[],man_y=now.man[];
q.pop();
for(re i=;i<=;++i)
{
int cx=x+dx[i],cy=y+dy[i];
if(check(x,dx[i],y,dy[i],man_x,man_y))
{
q.push(node(cx,cy,step+,x,y));
bz[cx][cy]=;
fix[cx][cy].px=x,fix[cx][cy].py=y;
fix[cx][cy].d=i;
if(s[cx][cy]=='T')
{
if(step+<ans)
{
ans=step+;
ansx=cx,ansy=cy;
}
}
}
}
}
} char shuchu[];
int rt=;
inline void print()
{
int num=;
int prx=ansx;
int pry=ansy;
int tt=;
while((prx!=box[])||(pry!=box[]))
{
hp ne=fix[prx][pry];
shuchu[++num]=xiang[ne.d];
for(re i=;i<=ne.cnt;++i)
{
shuchu[++num]=ren[ne.path[i]];
}
prx=ne.px;
pry=ne.py;
}
printf("Maze #%d\n",++rt);
for(re i=num;i>=;--i) cout<<shuchu[i];
puts("");
}
int main()
{
while()
{
while(q.size())q.pop();
memset(bz,,sizeof bz);
// memset(shuchu,0,sizeof shuchu);
memset(fix,,sizeof fix);
// memset(walk,0,sizeof walk);
ans=1e6;
scanf("%d%d",&r,&c);
if(r==&&c==)break;
for(re i=;i<=r;++i){
scanf("%s",s[i]+);
for(re j=;j<=c;++j){
if(s[i][j]=='B')box[]=i,box[]=j,bz[i][j]=;
if(s[i][j]=='S')per[]=i,per[]=j;
}
}
q.push(node(box[],box[],,per[],per[]));
Bfs();
if(ans==1e6)
{
printf("Maze #%d\n",++rt);
puts("Impossible.");
}
else print();
puts("");
}
return ;
}
Add/
1.关于POJ的special judge可能有点毒瘤,所以建议按照'N','S','W','E'的方向进行搜索。
2.数组不要开大了。
3.输出两个换行......
Pushing Boxes(广度优先搜索)的更多相关文章
- POJ1475 Pushing Boxes(双搜索)
POJ1475 Pushing Boxes 推箱子,#表示墙,B表示箱子的起点,T表示箱子的目标位置,S表示人的起点 本题没有 Special Judge,多解时,先最小化箱子被推动的次数,再最小化 ...
- [poj P1475] Pushing Boxes
[poj P1475] Pushing Boxes Time Limit: 2000MS Memory Limit: 131072K Special Judge Description Ima ...
- 图的广度优先搜索(BFS)
把以前写过的图的广度优先搜索分享给大家(C语言版) #include<stdio.h> #include<stdlib.h> #define MAX_VERTEX_NUM 20 ...
- 广度优先搜索(BFS)
定义 维基百科:https://en.wikipedia.org/wiki/Breadth-first_search 给定图G=(V,E)和一个可识别的源结点s,广度优先搜索对图G中的边进行系统性的探 ...
- 总结A*,Dijkstra,广度优先搜索,深度优先搜索的复杂度比较
广度优先搜索(BFS) 1.将头结点放入队列Q中 2.while Q!=空 u出队 遍历u的邻接表中的每个节点v 将v插入队列中 当使用无向图的邻接表时,复杂度为O(V^2) 当使用有向图的邻接表时, ...
- poj 1475 || zoj 249 Pushing Boxes
http://poj.org/problem?id=1475 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=249 Pushin ...
- ACM题目————图的广度优先搜索
题目描述 图的广度优先搜索类似于树的按层次遍历,即从某个结点开始,先访问该结点,然后访问该结点的所有邻接点,再依次访问各邻接 点的邻接点.如此进行下去,直到所有的结点都访问为止.在该题中,假定所有的结 ...
- SDUT 2141 【TEST】数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历
数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem ...
- HDU 1312 Red and Black DFS(深度优先搜索) 和 BFS(广度优先搜索)
Red and Black Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...
随机推荐
- leetcode 111. 二叉树的最小深度
题目描述: 给定一个二叉树,找出其最小深度. 最小深度是从根节点到最近叶子节点的最短路径上的节点数量. 说明: 叶子节点是指没有子节点的节点. 示例: 给定二叉树 [3,9,20,null,null, ...
- 去除img标签函数
需要去除一个长字符串中的img标签,网上找到了这个代码试试看,确实是有效的.代码如下: <?php function strip_tags_img($string='') { $pattern= ...
- Linux内核宏DEVICE_ATTR使用
1.前言 在Linux驱动程序编写中,使用DEVICE_ATTR宏,可以定义一个struct device_attribute设备属性,并使用sysfs的API函数,便可以在设备目录下创建出属性文件, ...
- Linux shell脚本单例模式实现
一.说明 关于单例模式,最开始的是一些小工具,运行起来后再点击运行时会提示已经运行了一个实例,觉得挺有意思但也没有很在意. 前段时间看了前领导的一段代码不太懂是做什么用的,同事查了下资料说是为了实现单 ...
- npm install 报错 error Unexpected end of JSON input while parsing near '...sShrinkwrap":false,"d' 解决办法
npm install 报错 : error Unexpected end of JSON input while parsing near '...sShrinkwrap":false,& ...
- Akka-CQRS(7)- CQRS Reader Actor 示范
我们在这篇通过一个具体CQRS-Reader-Actor的例子来示范akka-persistence的query端编程和应用.在前面的博客里我们设计了一个CQRS模式POS机程序的操作动作录入过程,并 ...
- LOJ2336 JOI2017 绳 贪心、构造
传送门 首先显然的是可以一开始先染好再做.每个点只会被染一次.最后只剩下两种颜色. 接下来是结论时间:序列可以反转的充要条件是除了首尾的极大颜色连通块以外其他极大颜色连通块长度为偶数. 证明充分性:考 ...
- Java面试宝典(2020版)
一.Java 基础 1. JDK 和 JRE 有什么区别? JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的开发环境和运行环境. JRE:Java ...
- 如何通过 IntelliJ IDEA 来提升 Java8 Stream 的编码效率
本文翻译整理自:https://winterbe.com/posts/2015/03/05/fixing-java-8-stream-gotchas-with-intellij-idea 作者:@Wi ...
- Python变量问题:命名、类型、赋值
1.变量问题 1.1变量命名: (1)变量名只能包含字母.数字和下划线.变量名可以字母或下划线开头,但不能以数字开头.例如,name1_,_name1都是合法的,但1name就不行(2)变量名中间不能 ...