題意:有兩個鬼和兩我的和牆,鬼先走,人再走,鬼每走過的地方都會複製一個新鬼,node
但新鬼只能等待舊鬼走完一次行程以後,下一次舊鬼再次開始新的行程時舊鬼才能移動,ios
舊鬼一個行程能走最多兩步,M能走三步,G能走一步。spa
問M和G能不能在被鬼抓住以前相遇,求最短期。.net
‘Z’表示鬼。code
第一次用曼哈頓距離來真正解決搜索,參考過別人的代碼,這份代碼感受仍是比較清楚和簡單的。blog
人每次移動一個距離都要進行一次曼哈頓距離的判斷,判斷人到該點時,是否是在鬼以前先到達,ci
注意,鬼先移動一個行程,人再移動一個行程。get
1 #include <iostream> 2 #include <cstring> 3 #include<vector> 4 #include <cstdio> 5 #include<string> 6 #include <cmath> 7 #include <map> 8 #include <queue> 9 #include <algorithm> 10 using namespace std; 11 12 #define inf (1LL << 31) - 1 13 #define rep(i,j,k) for(int i = (j); i <= (k); i++) 14 #define rep__(i,j,k) for(int i = (j); i < (k); i++) 15 #define per(i,j,k) for(int i = (j); i >= (k); i--) 16 #define per__(i,j,k) for(int i = (j); i > (k); i--) 17 18 const int N = 810; 19 int mv_x[] = {0, 0, 1, -1}; 20 int mv_y[] = {1, -1, 0, 0}; 21 char mp[N][N]; //原始地圖 22 int mx,my,hx,hy; //男女的座標 23 int g_x[2],g_y[2],g_l; //兩個鬼的座標 24 int n,m,STEP; 25 26 struct node{ 27 int x,y; 28 }; 29 30 queue <node > que[2]; 31 queue <node > qt; 32 33 inline void init(){ 34 g_l = 0; 35 STEP = 0; 36 } 37 38 void input(){ 39 40 init(); 41 42 rep(i,1,n){ 43 rep(j,1,m){ 44 cin >> mp[i][j]; 45 if(mp[i][j] == 'M') mx = i, my = j; 46 else if(mp[i][j] == 'G') hx = i, hy = j; 47 else if(mp[i][j] == 'Z') g_x[g_l] = i, g_y[g_l++] = j; 48 } 49 } 50 } 51 52 //是否越界 53 inline bool check(int x, int y){ 54 return x >= 1 && x <= n && y >= 1 && y <= m; 55 } 56 57 //曼哈頓距離判斷能不能相遇 58 inline bool M_dis(int dx,int dy){ 59 60 rep__(i,0,2){ 61 if(abs(dx - g_x[i]) + abs(dy - g_y[i]) <= 2 * STEP) return false; 62 } 63 return true; 64 } 65 66 void show(){ 67 68 rep(i,1,n){ 69 rep(j,1,m) cout << mp[i][j]; 70 cout << endl; 71 } 72 } 73 74 bool bfs(int pos, int steps, char me, char another){ 75 76 77 78 rep(i,1,steps){ //一個行程走幾輪 79 qt = que[pos]; //把這輪的全部開始點複製給qt 80 81 while(!qt.empty()){ 82 83 node tmp = qt.front(); 84 qt.pop(); 85 que[pos].pop(); 86 87 if(!M_dis(tmp.x,tmp.y)) continue; //剛開始進入bfs判斷一次曼哈頓距離,先判斷下人沒走以前鬼是否是能抓到人 88 89 rep__(p,0,4){ 90 91 int dx = tmp.x + mv_x[p]; 92 int dy = tmp.y + mv_y[p]; 93 94 //沒越界 不是牆 不是鬼 本身沒走過 知足曼哈頓距離 95 if(check(dx, dy) && mp[dx][dy] != 'X' && mp[dx][dy] != 'Z' && mp[dx][dy] != me 96 && M_dis(dx,dy)){ 97 98 if(mp[dx][dy] == another){ //遇到了另外一我的 99 100 // cout << "find the position " << dx << " " << dy << endl; 101 // cout << me <<" find " << mp[dx][dy] << endl; 102 return true; 103 } 104 105 mp[dx][dy] = me; //標記本身走過了這裏 106 que[pos].push(node{ dx, dy });//存在que[]中,表示下一輪的開始點 107 } 108 } 109 } 110 } 111 112 return false; 113 } 114 115 bool solve(){ 116 117 while (!que[0].empty()) que[0].pop(); 118 while (!que[1].empty()) que[1].pop(); 119 while (!qt.empty()) qt.pop(); 120 //que[0]表示M,que[1]表示G 121 que[0].push(node{ mx, my }); 122 que[1].push(node{ hx, hy }); 123 124 while (!que[0].empty() && !que[1].empty()){ // && 和 || 其實均可以 &&說明一我的不能走了
//那麼另外一我的也必定沒地方走了 125 126 STEP++;//步數加一,其實更好理解爲行程加一 127 if(bfs(0, 3,'M','G') || bfs(1, 1,'G','M')) return true; 128 129 } 130 131 return false; 132 } 133 134 int main(){ 135 136 ios::sync_with_stdio(false); 137 cin.tie(0); 138 139 int T; 140 cin >> T; 141 while (T--){ 142 cin >> n >> m; 143 input(); 144 145 if(solve()) cout << STEP << endl; 146 else cout << "-1" << endl; 147 // show(); 148 // cout << endl; 149 } 150 151 // getchar(); 152 153 return 0; 154 }