P1141 01迷宫

点击查看代码
#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是因为符合相邻搜索的原则,依次检查周围的元素
posted @ 2025-12-12 16:35  gosaky  阅读(1)  评论(0)    收藏  举报