3 5 6 XXXXXX XZ..ZX XXXXXX M.G... ...... 5 6 XXXXXX XZZ..X XXXXXX M..... ..G... 10 10 .......... ..X....... ..M.X...X. X......... .X..X.X.X. .........X ..XX....X. X....G...X ...ZX.X... ...Z..X..X
1 1 -1
題意就是給你一個迷宮,不對,就是說你如今被困在迷宮裏,要去和你GF見面,可是迷宮中還有人不能夠走的牆和會殺死人的幽靈,幽靈每一個單位時間都會往上下左右延申新的幽靈。
幽靈有兩個,M是你的位置,G是GF的位置。
幽靈每秒能夠延申兩格,你能夠每秒走三步,GF每秒只能走一步,若是在不被殺死的狀況和女友匯合就輸出最小單位時間,不然輸出-1.
(注意幽靈是能夠往牆上延申的)
由於兩我的均可以動,不用說,雙向BFS是確定的,不過有一點就是,如何實現每秒走三步以及判斷是否被殺死呢?
答案是我也不知道。這道題目就留給各位本身思考。
=7=嘻嘻 不鬧了。其實能夠換個思路去思考,咱們能夠用三個bfs代替走三步,可是如何判斷是否被殺死呢,其實這道題能夠不須要判斷是否被殺死,而是判斷人物走到可否在幽靈延申到某個位置以前走到那個位置,用曼哈頓距離判斷就好了。
提一下什麼是曼哈頓距離
經常使用距離度量方法有十一種,而咱們大部分時間只用到歐氏距離和曼哈頓距離。
設兩個點的座標(X1,Y1),(X2,Y2);
歐氏距離就是座標的直線距離 = sqrt((X2 - X1)2+(Y2 - Y1)2)
而曼哈頓距離就是以歐式距離爲斜邊構造直角三角形的兩直角邊和 = |X2 - X1| + |Y2 - Y1|
爲何有這麼多構造方式以及其區別,這篇博文就不詳細介紹了。
值得一題的是,由於是雙向搜索,因此須要開兩個二維數組或是一個三維數組分別標記你或者GF是否走過。
還有就是代碼BFS中的
1 int len = q[w].size(); 2 while(len--)
由於咱們不是一次就搜索完,咱們的BFS僅僅只是作走一步的做用,因此只把當前已經存的點的下一點存入就好了。如果以爲難以理解能夠替換成while(!q[w].empty)觀察每一步的輸出狀況。ios
代碼:
1 #include <iostream> 2 #include <string> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <sstream> 6 #include <iomanip> 7 #include <map> 8 #include <stack> 9 #include <deque> 10 #include <queue> 11 #include <vector> 12 #include <set> 13 #include <list> 14 #include <cstring> 15 #include <cctype> 16 #include <algorithm> 17 #include <iterator> 18 #include <cmath> 19 #include <bitset> 20 #include <ctime> 21 #include <fstream> 22 #include <limits.h> 23 #include <numeric> 24 25 using namespace std; 26 27 #define F first 28 #define S second 29 #define mian main 30 #define ture true 31 32 #define MAXN 1000000+5 33 #define MOD 1000000007 34 #define PI (acos(-1.0)) 35 #define EPS 1e-6 36 #define MMT(s) memset(s, 0, sizeof s) 37 typedef unsigned long long ull; 38 typedef long long ll; 39 typedef double db; 40 typedef long double ldb; 41 typedef stringstream sstm; 42 const int INF = 0x3f3f3f3f; 43 44 int fx[4][2]={1,0,-1,0,0,1,0,-1}; 45 char mp[810][810]; 46 int vis[2][810][810]; 47 int gx,gy,mx,my,n,m,step; //記錄座標,這裏的step指的是GF走的步數,應該理解成走了多少單位時間 48 pair<int,int>cur,z[2]; //z用來記錄幽靈位置 49 queue<pair<int,int> >q[2]; //分別記錄你和GF的路徑 50 51 bool check(pair<int,int> x){ 52 if(x.F < 0 || x.S < 0 || x.F >= n || x.S >= m || mp[x.F][x.S] == 'X') 53 return false; 54 if((abs(x.F-z[0].F)+abs(x.S-z[0].S)) <= 2*step || (abs(x.F-z[1].F)+abs(x.S-z[1].S)) <= 2*step) //判斷在幽靈延申到某個點以前是否能走到 55 return false; 56 return true; 57 } 58 59 int bfs(int w){ 60 pair<int,int>tp,next; 61 int len = q[w].size(); 62 while(len--){ //注意這裏不是搜完,由於是屢次搜索,只須要把當前步驟行進完就好了 63 tp = q[w].front(); 64 q[w].pop(); 65 if(!check(tp)) continue; 66 for(int i = 0; i < 4; i++){ 67 next.F = tp.F + fx[i][0]; 68 next.S = tp.S + fx[i][1]; 69 if(!check(next)) 70 continue; 71 if(!vis[w][next.F][next.S]){ 72 if(vis[1-w][next.F][next.S]) //判斷下一個點是否對方已經走過 73 return 1; 74 vis[w][next.F][next.S] = 1; 75 q[w].push(next); 76 } 77 } 78 } 79 return 0; 80 } 81 82 int solve(){ 83 while(!q[0].empty()) 84 q[0].pop(); 85 while(!q[1].empty()) 86 q[1].pop(); 87 88 cur.F = mx; 89 cur.S = my; 90 q[0].push(cur); 91 cur.F = gx; 92 cur.S = gy; 93 q[1].push(cur); 94 MMT(vis); 95 vis[0][mx][my] = vis[1][gx][gy] = 1; 96 step = 0; 97 98 while((!q[0].empty()) || (!q[1].empty())){ 99 step++; 100 if(bfs(0)) //經過三次bfs達到走三步 101 return step; 102 if(bfs(0)) 103 return step; 104 if(bfs(0)) 105 return step; 106 if(bfs(1)) 107 return step; 108 } 109 return -1; 110 } 111 112 int main(){ 113 ios_base::sync_with_stdio(false); 114 cout.tie(0); 115 cin.tie(0); 116 int t; 117 cin>>t; 118 while(t--){ 119 int cnt = 0; 120 cin>>n>>m; 121 for(int i = 0; i < n; i++) 122 cin>>mp[i]; 123 for(int i = 0; i < n; i++) 124 for(int j = 0; j < m; j++){ 125 if(mp[i][j] == 'G') 126 gx = i, gy = j; 127 if(mp[i][j] == 'M') 128 mx = i, my = j; 129 if(mp[i][j] == 'Z') 130 z[cnt].F = i, z[cnt++].S = j; 131 } 132 cout << solve() << endl; 133 } 134 return 0; 135 }