题解 P1141 [01迷宫]

题目描述

有一个仅由数字01组成的n×n格迷宫。若你位于一格0上,那么你可以移动到相邻4格中的某一格1上,同样若你位于一格1上,那么你可以移动到相邻4格中的某一格0上。

你的任务是:对于给定的迷宫,询问从某一格开始能移动到多少个格子(包含自身)。

输入格式

1行为两个正整数n,m

下面n行,每行n个字符,字符只可能是0或者1,字符之间没有空格。

接下来m行,每行2个用空格分隔的正整数i,j,对应了迷宫中第i行第j列的一个格子,询问从这一格开始能移动到多少格。

输出格式

m行,对于每个询问输出相应答案。

输入输出样例

输入 #1

2 2

01

10

1 1

2 2

输出 #1

4

4

说明/提示

所有格子互相可达。

对于20%的数据,n ≤ 10;

对于40%的数据,n ≤ 50;

对于50%的数据,m ≤ 5;

对于60%的数据,n ≤ 100, m ≤ 100;

对于100%的数据,n ≤ 1000, m ≤ 100000。

 

这道题既可以用dfs写,也可以用bfs写

code:

dfs:

 1 #include <bits/stdc++.h>
 2 #define REP(i, a, b) for (long long i = a; i <= b; ++i)
 3 #define ll long long
 4 #define N 1010
 5 using namespace std;
 6 
 7 ll n, m, cnt, dx[10] = {0, 1, -1, 0, 0}, dy[10] = {0, 0, 0, 1, -1}, ans[N * N], v[N][N], sum[N][N];
 8 char s[N][N];
 9 
10 inline ll read(){
11     ll s = 0, w = 1;
12     char ch = getchar();
13     while (ch < '0' || ch > '9'){
14         if (ch == '-') w *= -1;
15         ch = getchar();
16     }
17     while (ch >= '0' && ch <= '9'){
18         s = s * 10 + ch - '0';
19         ch = getchar();
20     }
21     return s * w;
22 }
23 
24 inline void dfs(ll x, ll y){                                                                        //深搜 
25     v[x][y] = 1;                                                                                    //打标记 
26     ans[cnt]++;                                                                                        //记答案 
27     sum[x][y] = cnt;                                                                                //划分连通块 
28     REP(i, 1, 4){
29         ll fx = x + dx[i], fy = y + dy[i];                                                            //取周围的任意一个点 
30         if (fx < 1 || fx > n || fy < 1 || fy > n || v[fx][fy] || s[fx][fy] == s[x][y]) continue;    //如果不够格直接跳过此循环 
31         dfs(fx, fy);                                                                                //继续搜 
32     }
33     
34 }
35 
36 inline void init(){                                                                                    //输入 
37     n = read(), m = read();
38     REP(i, 1, n)
39         REP(j, 1, n)
40             cin >> s[i][j];
41 }
42 
43 inline void work(){
44     init();
45     REP(i, 1, n)
46         REP(j, 1, n)
47             if (!sum[i][j]) cnt++, dfs(i, j);                                                        //初始化 
48     while (m--){
49         ll x = read(), y = read();
50         printf("%lld\n", ans[sum[x][y]]);
51     }
52 }
53 
54 int main(){
55     work();
56     return 0;
57 }

 

bfs:

 

 1 #include <bits/stdc++.h>
 2 #define REP(i, a, b) for (long long i = a; i <= b; ++i)
 3 #define ll long long
 4 #define N 1010
 5 using namespace std;
 6 
 7 ll n, m, cnt, dx[10] = {0, 1, -1, 0, 0}, dy[10] = {0, 0, 0, 1, -1}, ans[N * N], a[N][N], v[N][N], sum[N][N];
 8 char s[N][N];
 9 
10 queue < ll > qx, qy;
11 
12 inline ll read(){                                                                                //快读 
13     ll s = 0, w = 1;
14     char ch = getchar();
15     while (ch < '0' || ch > '9'){
16         if (ch == '-') w *= -1;
17         ch = getchar();
18     }
19     while (ch >= '0' && ch <= '9'){
20         s = s * 10 + ch - '0';
21         ch = getchar();
22     }
23     return s * w;
24 }
25 
26 inline void bfs(ll xx, ll yy){                                                                    //广搜 
27     v[xx][yy] = ans[cnt] = 1;                                                                    //打标记,记答案 
28     sum[xx][yy] = cnt;                                                                            //划分连通块 
29     qx.push(xx), qy.push(yy);                                                                    //入队 
30     while (!qx.empty() && !qy.empty()){                                                            //队列非空 
31         ll x = qx.front(), y = qy.front();                                                        //取队首 
32         qx.pop(), qy.pop();                                                                        //弹出队首 
33         REP(i, 1, 4){
34             ll fx = x + dx[i], fy = y + dy[i];                                                    //取周围的任意一个点 
35             if (fx > 0 && fx <= n && fy > 0 && fy <= n && !v[fx][fy] && s[fx][fy] != s[x][y]){    //判断是否够格 
36                 v[fx][fy] = 1;                                                                    //打标记 
37                 sum[fx][fy] = cnt;                                                                //加入(xx,yy)所在的连通块 
38                 ans[cnt]++;                                                                        //记答案 
39                 qx.push(fx), qy.push(fy);                                                        //入队 
40             }
41         }
42     }
43 }
44 
45 inline void init(){                                                                                //输入 
46     n = read(), m = read();
47     REP(i, 1, n)
48         REP(j, 1, n)
49             cin >> s[i][j];
50 }
51 
52 inline void work(){
53     init();
54     REP(i, 1, n)
55         REP(j, 1, n)
56             if (!sum[i][j]) cnt++, bfs(i, j);                                                    //初始化 
57     while (m--){
58         ll x = read(), y = read();
59         printf("%lld\n", ans[sum[x][y]]);
60     }
61 }
62 
63 int main(){
64     work();
65     return 0;
66 }

 

posted @ 2020-02-22 12:32  leoair  阅读(231)  评论(0)    收藏  举报