http://acm.hdu.edu.cn/showproblem.php?pid=1254
题意:推箱子游戏,在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,求最少的推箱子的次数,如果不能完成则输出-1。
思路:带嵌套的BFS~第一层BFS箱子,箱子每次移动前要再BFS一下人,看人能不能走到推动箱子的位置。
注意://因为人的位置不同时箱子可能可以到同一个位置两次,所以开4维(两维是箱子位置,两维是人的位置)数组标记。
#include<cstdio> #include<cstring> #include<queue> using namespace std; struct node{ int x,y,cnt; int px,py; }now,tmp,pnow,ptmp; queue<struct node>q;//BFS箱子的队列 queue<struct node>p;//BFS人的队列 int m,n; int maze[11][11]; bool vis[11][11][11][11]; bool pvis[11][11]; int dx[]={0,0,1,-1}; int dy[]={1,-1,0,0}; bool p_ok() { if(ptmp.x>=0&&ptmp.y>=0&&ptmp.x<m&&ptmp.y<n&&maze[ptmp.x][ptmp.y]!=1&&!(ptmp.x==now.x&&ptmp.y==now.y)&&!pvis[ptmp.x][ptmp.y]) return true; else return false; } bool p_bfs(int k)//简单的BFS,i为箱子要去的方向 { while(!p.empty()) p.pop(); memset(pvis,false,sizeof(pvis)); pnow.x=tmp.px;pnow.y=tmp.py; if(pnow.x==now.x-dx[k]&&pnow.y==now.y-dy[k])//特殊判断人就在箱子边上且正好是要推箱子的位置的情况 return true; pvis[pnow.x][pnow.y]=true; p.push(pnow); while(!p.empty()) { pnow=p.front(); p.pop(); for(int i=0;i<4;i++) { ptmp=pnow; ptmp.x+=dx[i]; ptmp.y+=dy[i]; if(p_ok()) { if(ptmp.x==now.x-dx[k]&&ptmp.y==now.y-dy[k]) return true; pvis[ptmp.x][ptmp.y]=true; p.push(ptmp); } } } return false; } bool ok() { if(tmp.x>=0&&tmp.y>=0&&tmp.x<m&&tmp.y<n&&maze[tmp.x][tmp.y]!=1&&!vis[tmp.x][tmp.y][tmp.px][tmp.py]) return true; else return false; } int bfs() { while(!q.empty()) q.pop(); now.cnt=0; vis[now.x][now.y][now.px][now.py]=true; q.push(now); while(!q.empty()) { now=q.front(); q.pop(); for(int i=0;i<4;i++) { tmp=now; tmp.x+=dx[i]; tmp.y+=dy[i]; if(ok()) { if(p_bfs(i))//判断人能否走到要推箱子的位置 { tmp.cnt++; if(maze[tmp.x][tmp.y]==3) return tmp.cnt; tmp.px=now.x;tmp.py=now.y; vis[tmp.x][tmp.y][now.px][now.py]=true; q.push(tmp); } } } } return -1; } int main() { int t; while(scanf("%d",&t)==1) { while(t--) { memset(vis,false,sizeof(vis)); scanf("%d %d",&m,&n); for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { scanf("%d",&maze[i][j]); if(maze[i][j]==2){now.x=i;now.y=j;} else if(maze[i][j]==4){now.px=i;now.py=j;}//初始化BFS箱子的第一个节点 } } printf("%d\n",bfs()); } } return 0; }
本 作品由 sdc1992创作,采用 知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行许可。
基于http://www.sdc1992.com/上的作品创作。
欢迎关注我的新博客:http://www.sdc1992.com/