【广度搜索】 01迷宫

【广度搜索】 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值