題目連接:https://www.luogu.org/problem/P1141html
有一個僅由數字00與11組成的n \times nn×n格迷宮。若你位於一格0上,那麼你能夠移動到相鄰44格中的某一格11上,一樣若你位於一格1上,那麼你能夠移動到相鄰44格中的某一格00上。ios
你的任務是:對於給定的迷宮,詢問從某一格開始能移動到多少個格子(包含自身)。數組
第11行爲兩個正整數n,mn,m。測試
下面nn行,每行nn個字符,字符只多是00或者11,字符之間沒有空格。優化
接下來mm行,每行22個用空格分隔的正整數i,ji,j,對應了迷宮中第ii行第jj列的一個格子,詢問從這一格開始能移動到多少格。spa
mm行,對於每一個詢問輸出相應答案。code
2 2 01 10 1 1 2 2
4 4
全部格子互相可達。orm
對於20\%20%的數據,n≤10n≤10;htm
對於40\%40%的數據,n≤50n≤50;blog
對於50\%50%的數據,m≤5m≤5;
對於60\%60%的數據,n≤100,m≤100n≤100,m≤100;
對於100\%100%的數據,n≤1000,m≤100000n≤1000,m≤100000。
先介紹採用裸的BFS,固然不能滿分。再介紹如何優化獲得滿分。
1 #include <iostream> 2 #include <stdio.h> 3 #include <math.h> 4 #include <algorithm> 5 #include <string.h> 6 7 using namespace std; 8 9 struct Node 10 { 11 int x, y; 12 }; 13 Node q[1000005]; 14 15 const int MAXN = 1005; 16 int n, m, a, b, c, d, front, last, step; 17 int pos[4][2] = {0, 1, 0, -1, 1, 0, -1, 0}; 18 char abc[MAXN][MAXN]; // 存儲輸入的矩陣信息 19 bool vis[MAXN][MAXN]; // 是否已經遍歷過該點 20 21 22 void bfs() 23 { 24 Node now; 25 now.x = a; 26 now.y = b; 27 vis[a][b] = 1; 28 29 front = last = 0; 30 q[last] = now; 31 last++; 32 while(front < last) 33 { 34 now = q[front++]; 35 for(int i = 0; i < 4; i++) 36 { 37 int nx = now.x + pos[i][0]; 38 int ny = now.y + pos[i][1]; 39 if(nx <= n && nx > 0 && ny <= n && ny > 0 40 && vis[nx][ny] == false 41 && abc[now.x][now.y] != abc[nx][ny]) 42 { 43 vis[nx][ny] = true; 44 q[last].x = nx; 45 q[last].y = ny; 46 step++; 47 last++; 48 } 49 } 50 } 51 } 52 53 int main() 54 { 55 cin >> n >> m; 56 for(int i = 1; i <= n; i++) 57 { 58 for(int j = 1; j <= n; j++) 59 { 60 cin >> abc[i][j]; 61 } 62 } 63 for(int i = 1; i <= m; i++) 64 { 65 cin >> a >> b; 66 step = 1; 67 bfs(); 68 cout << step << endl; 69 memset(vis, 0, sizeof(vis)); 70 } 71 return 0; 72 }
裸的BFS並無什麼技巧,只是注意q隊列不要過小,過小會致使WA。這個代碼會有3個測試點TLE。
之因此會出現TLE,主要是有不少次詢問,每次詢問都作了一次BFS,要優化代碼就要減小BFS的次數。注意到這樣一個事實:若是迷宮中存在連通塊,則連通塊中各格子到其餘格子的個數是相同的。而求連通塊自己就是利用BFS實現的。下面就是利用連通塊進行優化的代碼。
1 #include <iostream> 2 #include <stdio.h> 3 #include <math.h> 4 #include <algorithm> 5 #include <string.h> 6 7 using namespace std; 8 9 struct Node 10 { 11 int x, y; 12 }; 13 Node q[1000005]; 14 int cnt[1000005]; 15 16 const int MAXN = 1005; 17 int n, m, a, b, c, d, front, last, step, num; 18 int pos[4][2] = {0, 1, 0, -1, 1, 0, -1, 0}; 19 char abc[MAXN][MAXN]; // 存儲輸入的矩陣信息 20 bool vis[MAXN][MAXN]; // 是否已經遍歷過該點 21 int map[MAXN][MAXN]; // 用於對連通塊染色 22 23 24 void bfs() 25 { 26 Node now, next; 27 now.x = a; 28 now.y = b; 29 map[a][b] = num; 30 vis[a][b] = 1; 31 step = 1; 32 33 front = last = 0; 34 q[last] = now; 35 last++; 36 while(front < last) 37 { 38 now = q[front++]; 39 for(int i = 0; i < 4; i++) 40 { 41 int nx = now.x + pos[i][0]; 42 int ny = now.y + pos[i][1]; 43 if(nx <= n && nx > 0 && ny <= n && ny > 0 44 && vis[nx][ny] == false 45 && abc[now.x][now.y] != abc[nx][ny]) 46 { 47 vis[nx][ny] = true; 48 q[last].x = nx; 49 q[last].y = ny; 50 map[nx][ny] = num; 51 step++; 52 last++; 53 } 54 } 55 } 56 cnt[num] = step; 57 num++; 58 } 59 60 int main() 61 { 62 cin >> n >> m; 63 for(int i = 1; i <= n; i++) 64 { 65 for(int j = 1; j <= n; j++) 66 { 67 cin >> abc[i][j]; 68 } 69 } 70 num = 1; 71 for(int i = 1; i <= m; i++) 72 { 73 cin >> a >> b; 74 if(map[a][b] == 0) 75 { 76 bfs(); 77 } 78 cout << cnt[map[a][b]] << endl; 79 } 80 return 0; 81 }
其中的map數組是用來存儲連通塊的染色信息的。若是格子對應的map數據爲0,說明沒有作過BFS。cnt數組存儲着每一個連通塊所對應的格子個數。通過此次優化,就能夠AC了。