题目描述
有一个仅由数字 0 与 1 组成的 n×n 格迷宫。若你位于一格 0 上,那么你可以移动到相邻 4 格中的某一格 1 上,同样若你位于一格 1 上,那么你可以移动到相邻 4 格中的某一格 0 上。
你的任务是:对于给定的迷宫,询问从某一格开始能移动到多少个格子(包含自身)。
输入格式
有一个仅由数字 0 与 1 组成的 n×n 格迷宫。若你位于一格 0 上,那么你可以移动到相邻 4 格中的某一格 1 上,同样若你位于一格1 上,那么你可以移动到相邻 4 格中的某一格 0 上。
你的任务是:对于给定的迷宫,询问从某一格开始能移动到多少个格子(包含自身)。
输出格式
m 行,对于每个询问输出相应答案。
输入样例
2 2
01
10
1 1
2 2
输出样例
4
4
说明
所有格子互相可达,对于 100% 的数据 n≤1000,m≤100000。
解析:如果对于每个询问的坐标进行bfs,那么就会超时了,对于一个点(x1,y1)能到的点(x2,y2),那么(x2,y2)也可以到(x1,y1),因此他们对于最多能走几个方格的答案值是相同的,因此我们可以预处理每个点的答案,对于每一组询问直接输出即可。
小方法:从(x,y)开始bfs,同时记录下他能到的所有点(数组队列什么都行🙃),然后对于这个联通块,答案都是相同的,结束的时候赋值dist[ ][ ]记录下答案即可。
#include <bits/stdc++.h>
using namespace std;
const int N=1005;
typedef pair<int,int> PII;
int a[N][N],dist[N][N],n,m;
bool st[N][N];
void bfs(int x,int y)
{
int cnt=1;
queue<PII> path;//保存记录(x,y)能到的所有点
queue<PII> q;
st[x][y]=true;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
q.push({x,y});
path.push({x,y});//包括自身
while(q.size())
{
int x1=q.front().first;
int y1=q.front().second;
q.pop();
for(int i=0;i<4;i++)
{
int x2=x1+dx[i];
int y2=y1+dy[i];
if(!(x2>=1&&x2<=n&&y2>=1&&y2<=n)) continue;//越界
if((a[x2][y2]!=a[x1][y1])&&!st[x2][y2])
{
cnt++;
q.push({x2,y2});
path.push({x2,y2});//保存
st[x2][y2]=true;//标记访问
}
}
}
while(path.size())//对于这个联通块,赋值答案
{
int x=path.front().first;
int y=path.front().second;
path.pop();
dist[x][y]=cnt;
}
}
void solve()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) scanf(" %c",&a[i][j]);//输入迷宫
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) if(!st[i][j]) bfs(i,j);//如果没访问过
while(m--)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",dist[x][y]);
}
}
int main()
{
solve();
return 0;
}