推箱子
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6767 Accepted Submission(s): 1908
Problem Description
推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子,因此如果箱子被推到一个角上(如图2)那么箱子就不能再被移动了,如果箱子被推到一面墙上,那么箱子只能沿着墙移动.
现在给定房间的结构,箱子的位置,搬运工的位置和箱子要被推去的位置,请你计算出搬运工至少要推动箱子多少格.
现在给定房间的结构,箱子的位置,搬运工的位置和箱子要被推去的位置,请你计算出搬运工至少要推动箱子多少格.
Input
输入数据的第一行是一个整数T(1<=T<=20),代表测试数据的数量.然后是T组测试数据,每组测试数据的第一行是两个正整数M,N(2<=M,N<=7),代表房间的大小,然后是一个M行N列的矩阵,代表房间的布局,其中0代表空的地板,1代表墙,2代表箱子的起始位置,3代表箱子要被推去的位置,4代表搬运工的起始位置.
Output
对于每组测试数据,输出搬运工最少需要推动箱子多少格才能帮箱子推到指定位置,如果不能推到指定位置则输出-1.
Sample Input
1
5 5
0 3 0 0 0
1 0 1 4 0
0 0 1 0 0
1 0 2 0 0
0 0 0 0 0
Sample Output
4
Author
Ignatius.L & weigang Lee
Recommend
代码信息量有点大; 总体来说就是用bfs过程来记录状态
#include <queue> #include <cstdio> #include <cstring> #define N 8 using namespace std; int xiangx, xiangy; int ac[4][2]={0, 1, 0, -1, -1, 0, 1, 0}; int n, m, flag, G[N][N], mark[N][N][N][N], markk[N][N]; struct dian { int x, y; int renx, reny; int step; } st, end; struct ren { int x, y; }vv, stt; int bffs(ren stt) { queue<ren> q; markk[stt.x][stt.y]=1; q.push(stt); ren v, vn; while(!q.empty()) { vn=q.front(); q.pop(); if(vv.x==vn.x&&vv.y==vn.y) //人在箱子后边; { return 1; } for(int i=0; i<4; i++) { v.x=vn.x+ac[i][0]; v.y=vn.y+ac[i][1]; if(v.x<0||v.x>=n||v.y<0||v.y>=m) continue; if(G[v.x][v.y]==1) continue; if(v.x==xiangx&&v.y==xiangy) continue; //unknow, 应该是人到达不了箱子初始位置, 形成一个环。 if(markk[v.x][v.y]==1) continue; markk[v.x][v.y]=1; q.push(v); } } return 0; } void bfs(dian st) { queue<dian>q; q.push(st); mark[st.x][st.y][st.renx][st.reny]=1; dian v, vn; while(!q.empty()) { vn=q.front(); q.pop(); if(vn.x==end.x&&vn.y==end.y) { flag=1; printf("%d ", vn.step); return; } for(int i=0; i<4; i++) { v.x=vn.x+ac[i][0]; v.y=vn.y+ac[i][1]; v.step=vn.step+1; v.renx=vn.x; v.reny=vn.y; vv.x=vn.x-ac[i][0]; //人推箱子必须得在箱子前进方向的后边; vv.y=vn.y-ac[i][1]; if(v.x<0 || v.x>=n || v.y<0 || v.y>=m) continue; if(G[v.x][v.y]==1) continue; if(G[vv.x][vv.y]==1||vv.x<0||vv.x>=n||vv.y<0||vv.y>=m) continue; if(mark[v.x][v.y][v.renx][v.reny]) continue; //推走一步后, 箱子和人所在坐标状态; stt.x=vn.renx; //原状态; stt.y=vn.reny; xiangx=vn.x; xiangy=vn.y; memset(markk, 0, sizeof(markk)); if(!bffs(stt)) continue; mark[v.x][v.y][v.renx][v.reny]=1; //判断人是否可以在箱子前进方向初始位置的后方; q.push(v); } } } int main() { int T; scanf("%d", &T); while(T--) { flag=0; scanf("%d%d", &n, &m); for(int i=0; i<n; i++) for(int j=0; j<m; j++) { scanf("%d", &G[i][j]); if(G[i][j]==2) { st.x=i; st.y=j; xiangx=i; xiangy=j; } if(G[i][j]==3) { end.x=i; end.y=j; } if(G[i][j]==4) { st.renx=i; st.reny=j; } } st.step=0; memset(mark, 0, sizeof(mark)); memset(markk, 0, sizeof(markk)); bfs(st); if(!flag) printf("-1 "); } return 0; }