【广度搜索】 01迷宫
题目描述
有一个仅由数字0与1组成的n×n格迷宫。若你位于一格0上,那么你可以移动到相邻4格中的某一格1上,同样若你位于一格1上,那么你可以移动到相邻4格中的某一格0上。
你的任务是:对于给定的迷宫,询问从某一格开始能移动到多少个格子(包含自身)。
输入格式
第1行为两个正整数n,m。
下面n行,每行n个字符,字符只可能是0或者1,字符之间没有空格。
接下来m行,每行2个用空格分隔的正整数i,j,对应了迷宫中第ii行第jj列的一个格子,询问从这一格开始能移动到多少格。
输出格式 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。
解法:
原本做法是 for一个循环,问一次哪个点,就代入进去bfs 一次,输出结果。
这样数量大的时候还是超时。。。。。。
然后才懂 原来 -问的那个点 它能走到的格子,每个也是能走到的格子数量都是一样的。
就是说 一个点,它能联通的那些点都是同样的格子数。
那就再开个数组ans【】,把 联通的点 color 标记为一样 存入数组ans【color】 ,值为他们的数量,就是能走到的格子数
遍历所有点, 最后问哪个点的时候输出哪个ans【】就ok
代码
#include<iostream>
using namespace std;
#include<queue>
#include<cstring>
#include<cstdio>
int n,m;
bool map[1005][1005];
int dir[4][2] = {{0,1},{-1,0},{0,-1},{1,0}};
int vis[1005][1005];
bool in(int x,int y){
return 1<=x &&x<=n && 1<=y && y<=n;
}
int color =0,cnt =0;
int ans[100000010];
void bfs(int x,int y){
int ans =1;
queue<pair<int,int> > q;
q.push(make_pair(x,y));
vis[x][y] = color;
while(!q.empty()){
for(int i=0;i<4;i++){
int tx = q.front().first + dir[i][0]; //上下左右走 看 相邻格 符合就压入队列
int ty = q.front().second + dir[i][1];
//cout<<"tx: "<<tx<<" "<<ty<<!vis[tx][ty]<<endl;
//cout<<"map:"<<map[tx][ty] <<" "<<map[q.front().first][q.front().second]<<endl;
if(in(tx,ty) && !vis[tx][ty] &&
map[tx][ty] !=map[q.front().first][q.front().second]){
ans++;
q.push(make_pair(tx,ty));
vis[tx][ty] =color;
}
}
cnt++;
q.pop();
}
//cout<<ans<<endl;
//printf("%d\n",ans);
}
int main(){
scanf("%d%d",&n,&m);
int k=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
char s; //构建地图
cin>>s;
//scanf("%c",&s);
if(s == '1'){
map[i][j] =1;
}else{
map[i][j] = 0;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(!vis[i][j]){ //把地图上每个点都先记录步数cnt。
color++; //能相互走到的点的步数是一样的,所以可以都标记为同的color。
bfs(i,j);
ans[color] = cnt;
cnt =0;
}
}
}
for(int i=0;i<m;i++){
int x,y;
cin>>x>>y; // 每次问哪个点 就输出
cout<<ans[vis[x][y]]<<endl;
}
return 0;
}