这题做的一把鼻涕一把泪,果断考虑不周555
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
1 #include <cstdio> 2 #include <queue> 3 using namespace std; 4 const int dir[4][2] = {0,1,0,-1,1,0,-1,0}; 5 int m, n, map[7][7]; 6 7 struct node 8 { 9 int x, y, step; 10 int man_x, man_y; 11 12 bool check(void) 13 { 14 if(x>=0 && x<m && y>=0 && y<n) 15 { 16 if(map[x][y] != 1) 17 { 18 return true; 19 } 20 } 21 return false; 22 } 23 }start, man, temp, next, u, v; 24 25 bool BFS_Man(void) 26 { 27 start.x = temp.man_x; 28 start.y = temp.man_y; 29 30 int mark[7][7] = {0}; 31 mark[start.x][start.y] = 1; 32 33 queue<node>que; 34 que.push(start); 35 36 while(!que.empty()) 37 { 38 u = que.front(); 39 que.pop(); 40 if(u.x == man.x && u.y == man.y) 41 { 42 return true; 43 } 44 for(int i=0;i<4;i++) 45 { 46 v.x = u.x + dir[i][0]; 47 v.y = u.y + dir[i][1]; 48 if(v.check() && !mark[v.x][v.y] && (v.x != temp.x || v.y != temp.y)) //越界,撞墙,重复,撞箱子 49 { 50 mark[v.x][v.y] = 1; 51 que.push(v); 52 } 53 } 54 } 55 return false; 56 } 57 58 int BFS_Box(void) 59 { 60 int mark[7][7][4] = {0}; //判重的时候需要一个三维数组,箱子从不同方向过来,人的位置是不一样的,也就意味着状态不一样 61 62 queue<node>que; 63 que.push(start); 64 65 while(!que.empty()) 66 { 67 temp = que.front(); 68 que.pop(); 69 70 if(map[temp.x][temp.y] == 3) //找到返回步数 71 { 72 return temp.step; 73 } 74 75 for(int i=0;i<4;i++) 76 { 77 next.x = temp.x + dir[i][0]; 78 next.y = temp.y + dir[i][1]; 79 next.step = temp.step + 1; 80 if(next.check() && mark[next.x][next.y][i] == 0) //判断越界,撞墙,重复 81 { 82 man.x = temp.x - dir[i][0]; 83 man.y = temp.y - dir[i][1]; //人移动的目标坐标 84 if(man.check()) //判断目标坐标是否越界,撞墙 85 { 86 if(BFS_Man()) //搜索判断人是否可以移动到目标点 87 { 88 next.man_x = temp.x; 89 next.man_y = temp.y; //更新当前人坐标 90 91 mark[next.x][next.y][i] = 1; 92 que.push(next); 93 } 94 } 95 } 96 } 97 } 98 return -1; 99 } 100 101 int main() 102 { 103 int T; 104 scanf("%d",&T); 105 while(T--) 106 { 107 scanf("%d%d",&m,&n); 108 for(int i=0;i<m;i++) 109 { 110 for(int j=0;j<n;j++) 111 { 112 scanf("%d",&map[i][j]); 113 if(map[i][j] == 2) //记录箱子起点 114 { 115 start.x = i; 116 start.y = j; 117 start.step = 0; 118 } 119 else if(map[i][j] == 4) //记录人起点 120 { 121 start.man_x = i; 122 start.man_y = j; 123 } 124 } 125 } 126 printf("%d ",BFS_Box()); 127 } 128 return 0; 129 }