题目描述
有一个仅由数字 0 与 1组成的 n×n 格迷宫。若你位于一格0上,那么你可以移动到相邻 4 格中的某一格 1 上,同样若你位于一格1上,那么你可以移动到相邻 4 格中的某一格 0 上。
你的任务是:对于给定的迷宫,询问从某一格开始能移动到多少个格子(包含自身)。
输入输出格式
输入格式:
第 11 行为两个正整数 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 。
思路
一开始想的是bfs,不过提交代码之后,发现超时了,仔细一想,既然一个位置能到达另一个位置,那么反过来一样能达到,因此,可以把一个位置能到达的所有位置看成是一个连通块,在一个连通块内,任何位置所到达的格子一样,这样一来,把连通块的位置都进行标记,再搜索没标记的,再看成一个连通块,直至所有位置搜索完
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | #include <iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<string> #include<map> using namespace std; const int MAXN=1e3+10; string s[MAXN]; int d[4][2]={0,1,0,-1,1,0,-1,0}; int vis[MAXN][MAXN]; int f[MAXN][MAXN]; int b[1000005][2]; struct node { int x,y; }; int res,n,m; void bfs(int x,int y) // 常规bfs { queue<node> que; node e1,e2; e1.x=x,e1.y=y; res++; b[res][0]=x; // 对经过的位置进行记录 b[res][1]=y; que.push(e1); vis[e1.x][e1.y]=0; //标记 while(que.size()){ e1=que.front();que.pop(); for(int i=0;i<4;i++){ e2.x=e1.x+d[i][0]; e2.y=e1.y+d[i][1]; if(e2.x>=0&&e2.x<n&&e2.y>=0&&e2.y<n&&vis[e2.x][e2.y]){ if(s[e1.x][e1.y]!=s[e2.x][e2.y]){ res++; b[res][0]=e2.x; // 记录 b[res][1]=e2.y; que.push(e2); vis[e2.x][e2.y]=0; } } } } } int main() { int x,y; cin >> n>>m; for(int i=0;i<n;i++) cin>>s[i]; memset(vis,1,sizeof(vis)); for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(vis[i][j]){ //搜索未经过的位置 vis[i][j]=0; res=0; bfs(i,j); for(int k=1;k<=res;k++) // 把一次搜索所经过的路径看成是一个连通块 f[b[k][0]][b[k][1]]=res; //连通块内所能到达的格子都一样,即联通块的大小 } while(m--){ cin>>x>>y; cout<<f[x-1][y-1]<<endl; //直接输出 } return 0; } |
这一题,也可以用dfs做,思路差不多,代码更加简洁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #include <iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<string> #include<map> using namespace std; const int MAXN=1e3+10; string s[MAXN]; int d[4][2]={0,1,0,-1,1,0,-1,0}; int vis[MAXN][MAXN],f[MAXN][MAXN]; int b[1000005][2]; int res,n; void dfs(int x,int y) { res++; b[res][0]=x,b[res][1]=y; for(int i=0;i<4;i++){ int nx=x+d[i][0],ny=y+d[i][1]; if(nx>=0&&nx<n&&ny>=0&&ny<n&&vis[nx][ny]&&s[nx][ny]!=s[x][y]){ vis[nx][ny]=0; dfs(nx,ny); } } } int main() { int x,y,m; cin >> n>>m; for(int i=0;i<n;i++) cin>>s[i]; memset(vis,1,sizeof(vis)); for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(vis[i][j]){ vis[i][j]=0; res=0; dfs(i,j); for(int k=1;k<=res;k++) f[b[k][0]][b[k][1]]=res; } while(m--){ cin>>x>>y; cout << f[x-1][y-1]<<endl; } return 0; } |