洛谷 p1141 宽度优先搜索 bfs

题目描述
有一个仅由数字0与1组成的n×n格迷宫。若你位于一格0上,那么你可以移动到相邻4格中的某一格1上,同样若你位于一格1上,那么你可以移动到相邻44格中的某一格0上。
你的任务是:对于给定的迷宫,询问从某一格开始能移动到多少个格子(包含自身)。
输入格式
第1行为两个正整数n,m。
下面n行,每行n个字符,字符只可能是0或者1,字符之间没有空格。
接下来m行,每行2个用空格分隔的正整数i,j,对应了迷宫中第i行第j列的一个格子,询问从这一格开始能移动到多少格。
输出格式
mm行,对于每个询问输出相应答案。

输入
2 2
01
10
1 1
2 2
输出
4
4

刚开始以为宽搜就可以
就有了以下的代码

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cstdio>

using namespace std;

int n,m,bx,by,step;

struct node{
	int x,y;
};

int map[100010][1000010],visit[100010][100010];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int bfs()
{
	queue<node>q;
	node t={bx,by};
	q.push(t);
	while(!q.empty()){
		node p;
		p=q.front();
		q.pop();
		for(int i=0;i<4;i++)
		{
		t.x=p.x+dx[i];
		t.y=p.y+dy[i];
		}
		if(t.x>=1&&t.x<=n&&t.y>=1&&t.y<=n&&map[t.x][t.y]==0&&!visit[t.x][t.y])
		{
			visit[t.x][t.y]=1;
			step++;
			q.push(t);
		}
	}
	return step;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	scanf("%d",&map[i][j]);
	while(m--)
	{
		scanf("%d%d",&bx,&by);
		int ans=bfs();
		
		printf("%d",ans);
	}
}

后来超时 再一检查 很明显,这题数据很大,读一组查一遍必然爆炸。

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cstdio>

using namespace std;

int n,m,bx,by,d,sum;
char ch;

struct node{
	int x,y;
};

int map[1010][1010],flag[1010][1010],a[10000010];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
void bfs()
{
	queue<node>q;
	for(int i=1;i<=n;i++)//查一遍所有的点
	for(int j=1;j<=n;j++)
	{
		node t={i,j};
		if(flag[t.x][t.y]==0)//如果他还未属于任何一个连通块
		{
			d++;//创建一个编号为d++的新连通块
			flag[t.x][t.y]=d;//把点放入此连通块
			q.push(t);入队 向四周搜索
			sum=1;//记录目前新连通块点的数量
		}
	while(!q.empty()){//队列不为空
		node p;
		p=q.front();//取出队头
		q.pop();//删除队头
		for(int i=0;i<4;i++)
		{
		t.x=p.x+dx[i];
		t.y=p.y+dy[i];
		if(t.x>=1&&t.x<=n&&t.y>=1&&t.y<=n&&(map[t.x][t.y]!=map[p.x][p.y])&&!flag[t.x][t.y])//满足不超边界且不属于任何一连通块
		{
			flag[t.x][t.y]=d;
			sum++;//计数
			q.push(t);
		}
	}
}
	a[d]=sum;
}
}
int main()
{
	int ans; 
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	{
		scanf(" %c",&ch);
		if(ch=='1')
		map[i][j]=1;
		else
		map[i][j]=0;
	}
	bfs();
	while(m--)
	{
		scanf("%d%d",&bx,&by);
		ans=a[flag[bx][by]];
		
		printf("%d\n",ans);
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值