题解 P1141 [01迷宫]
题目描述
有一个仅由数字0与1组成的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 }
浙公网安备 33010602011771号