转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
以前就做过的一题,重温一下
推箱子游戏,首先广搜箱子的路径,每一次移动都要判断人是否能到达指定位置(BFS,DFS都行),我采用两次BFS解决问题
在箱子的移动中,判重的时候需要一个三维数组,箱子从不同方向过来,人的位置是不一样的,也就意味着状态不一样
/* ID:cxlove */ #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> #define LL unsigned long long using namespace std; int n,m,T; int way[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; int str[10][10]; struct Node{ int x,y,step; int mmap[10][10]; bool check(){ if(x>=0&&x<n&&y>=0&&y<m) return true; return false; } }s,e,u,v,ss,ee,uu,vv; bool bfs_people(Node n1){ //搜索人是否能到达指定位置 queue<Node>que; ss=n1; bool flag[10][10]; memset(flag,false,sizeof(flag)); for(int i=0;i<n;i++){ //找到人的起点 for(int j=0;j<m;j++) if(n1.mmap[i][j]==4){ ss.x=i; ss.y=j; ss.step=0; } } if(ss.x==ee.x&&ss.y==ee.y) return true; que.push(ss); flag[ss.x][ss.y]=true; while(!que.empty()){ uu=que.front(); que.pop(); for(int i=0;i<4;i++){ vv=uu; vv.step++; vv.x+=way[i][0]; vv.y+=way[i][1]; if(vv.check()&&flag[vv.x][vv.y]==false&&(n1.mmap[vv.x][vv.y]!=1&&n1.mmap[vv.x][vv.y]!=2)){ //目标点不是墙也不是箱子 flag[vv.x][vv.y]=true; if(vv.x==ee.x&&vv.y==ee.y) return true; que.push(vv); } } } return false; } int bfs_box(){ //搜索箱子 int flag[10][10][4]; queue<Node>que; que.push(s); memset(flag,false,sizeof(flag)); while(!que.empty()){ u=que.front(); que.pop(); for(int i=0;i<4;i++){ v=u; v.x+=way[i][0]; v.y+=way[i][1]; v.step++; if(v.check()&&str[v.x][v.y]!=1&&flag[v.x][v.y][i]==false){ //人的目标位置 ee.x=u.x-way[i][0]; ee.y=u.y-way[i][1]; if(ee.check()==false) continue; if(bfs_people(v)){ //更新地图,箱子和人的位置 swap(v.mmap[v.x][v.y],v.mmap[u.x][u.y]); swap(v.mmap[ee.x][ee.y],v.mmap[ss.x][ss.y]); flag[v.x][v.y][i]=true; if(str[v.x][v.y]==3) return v.step; que.push(v); } } } } return -1; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); for(int i=0;i<n;i++) for(int j=0;j<m;j++){ scanf("%d",&str[i][j]); s.mmap[i][j]=str[i][j]; if(str[i][j]==2){ //标注箱子起点 s.x=i; s.y=j; s.step=0; } } printf("%d\n",bfs_box()); } return 0; }