洛谷 P1141 01迷宮題解

題目連接: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

輸入輸出樣例

輸入 #1
2 2
01
10
1 1
2 2
輸出 #1
4
4

說明/提示

全部格子互相可達。orm

對於20\%20%的數據,n≤10n10;htm

對於40\%40%的數據,n≤50n50;blog

對於50\%50%的數據,m≤5m5;

對於60\%60%的數據,n≤100,m≤100n100,m100;

對於100\%100%的數據,n≤1000,m≤100000n1000,m100000。


題解

先介紹採用裸的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了。

相關文章
相關標籤/搜索