点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int n,m;
char g[N][N];
//联通块对应的id
int cid[N][N];
//连通块对应的大小
int csize[N*N];
//连通块计数器,记录有多少个连通块了,顺便对应id
int cnt;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
void bfs(int sx,int sy)
{
//如果已经访问过就直接结束
if(cid[sx][sy]!=0) return;
cnt++;
//放入首个元素
queue<pair<int,int>> q;
q.push({sx,sy});
cid[sx][sy]=cnt;
//记录大小
int size=0;
//搜索主程序
while(!q.empty()){
//取出队首
auto [x,y]=q.front();
q.pop();
size++;
char cur=g[x][y];
//扩散搜索
for(int i=0;i<4;i++){
int nx=x+dx[i];
int ny=y+dy[i];
//检查边界,是否访问,是否符合移动规则
if(nx<1||nx>n||ny<1||ny>n) continue;
if(cid[nx][ny]!=0) continue;
if(g[nx][ny]==cur) continue;
//记录对应的id
cid[nx][ny]=cnt;
q.push({nx,ny});
}
}
csize[cnt]=size;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
//读入迷宫
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++) cin>>g[i][j];
}
//预处理,找出所有连通块
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(cid[i][j]==0) bfs(i,j);
}
}
//处理查询
while(m--){
int x,y;
cin>>x>>y;
//取出对应的连通块id
int id=cid[x][y];
//输出对应连通块的大小
cout<<csize[id]<<endl;
}
return 0;
}
题目要求每一格可以依据规则移动多少步,基于这个图形的矩阵以及移动规则,我们可以用bfs+并查集的方法解决。
首先,使用并查集是因为,这道题具有连通块的思想,一个单元能通过步骤到达另一个位置,那么,这个单元和最终的位置以及它走过的所有位置就构成了一个块,这个块之间的所有单元可以互相抵达
我们可以不用传统的祖宗节点方法,而是,开一个和矩阵大小相同的数组,给他标记上id
然后,使用bfs是因为符合相邻搜索的原则,依次检查周围的元素