题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1072
题目大意:
在n×m的地图上,0表示墙,1表示空地,2表示人,3表示目的地,4表示有定时炸弹重启器。定时炸弹的时间是6,人走一步所需要的时间是1。每次可以上、下、左、右移动一格。当人走到4时如果炸弹的时间不是0,可以重新设定炸弹的时间为6。如果人走到3而炸弹的时间不为0时,成功走出。求人从2走到3的最短时间。
思路:
从起点进行BFS,每个节点有四个属性,x,y,step(当前步数),time(剩余时间)
由于每个节点可以多次访问,所以BFS时的vis数组失效,但是每个炸弹重启器的点必须是第一次到达才是最优解,因为每次到该点,可以time变为6,可以再走6步,要是再次回来也只能和之前一样最多走6步,一定不是最优解。所以对每个炸弹重启点进行vis标记。每走一步step+1,time-1
1 #include<iostream> 2 #include<queue> 3 using namespace std; 4 int n, m; 5 int dir[4][2] = {1,0,0,1,-1,0,0,-1}; 6 struct node 7 { 8 int x, y, time, step;//time表示炸弹剩余时间,step表示当前步数 9 node(){ 10 } 11 node(int x, int y, int time, int step):x(x), y(y), time(time), step(step){ 12 } 13 }; 14 int x1, y1, x2, y2; 15 int Map[20][20]; 16 bool judge(int x, int y) 17 { 18 return (x > 0 && x <= n && y > 0 && y <= m && Map[x][y] != 0); 19 } 20 int bfs() 21 { 22 queue<node>q; 23 node now(x1, y1, 6, 0); 24 q.push(now); 25 while(!q.empty()) 26 { 27 node now = q.front(); 28 q.pop(); 29 //cout<<now.x<<" "<<now.y<<" "<<now.time<<" "<<now.step<<endl; 30 if(Map[now.x][now.y] == 3) 31 { 32 return now.step; 33 } 34 for(int i = 0; i< 4; i++) 35 { 36 int xx = now.x + dir[i][0]; 37 int yy = now.y + dir[i][1]; 38 if(!judge(xx, yy))continue; 39 int step = now.step + 1; 40 int time = now.time - 1; 41 if(time <= 0)continue; 42 if(Map[xx][yy] == 4)time = 6, Map[xx][yy] = 0;//如果走到了时间调整器,就恢复时间,并且标记该点变成0,使得不能再走 43 q.push(node(xx, yy, time, step)); 44 } 45 } 46 return -1; 47 } 48 int main() 49 { 50 int T; 51 cin >> T; 52 while(T--) 53 { 54 cin >> n >> m; 55 for(int i = 1; i <= n; i++) 56 { 57 for(int j = 1; j <= m; j++) 58 { 59 cin >> Map[i][j]; 60 if(Map[i][j] == 2) 61 { 62 x1 = i, y1 = j; 63 } 64 if(Map[i][j] == 3) 65 { 66 x2 = i, y2 = j; 67 } 68 } 69 } 70 cout<<bfs()<<endl;; 71 } 72 return 0; 73 }