01迷宫题解(bfs,联通块)

时间:2021-11-23 15:48:11

题目https://www.luogu.org/problemnew/show/P1141

这个题解主要针对我个人出现的一些问题和注意的地方。

解题思路

首先说一下联通块

联通块这个比较抽象,举个例子就是假设一条鱼在一个池塘里游泳,那么在时间不限的情况下,小鱼会游过池塘的所有位置,而这个与小鱼的出发点是无关的。

所以在本题中,假设从一个坐标开始,对他能经过的所有点进行标记,那么在剩下的询问中,如果询问的坐标已经被标记,那么它所经过的点与假设的坐标是相同的,所以就可以创建一个统计格子数目的数组cnt和一个联通图int数组_map与迷宫的坐标一一对应,假设第i次询问可以经过n个点,那么就把这个联通图所有经过的点赋值为i,并赋值cnt[i]=经过的格子数。在剩下的询问中,如果已经被标记,则直接输出_map对应的i所对应的cnt数组的值。

我本人出现的错误(一直不知道哪里错了,看了很长时间才反应过来)

一开始并没有使用_map作为联通图,而是直接在原迷宫内修改,但是在询问过多的情况下,两位数的值就不能赋值在一个位置中(当时不知道为什么这么写,有点懵),所以在情况超过9次之后就会出错。具体怎么个情况就是代码中注释的部分。

说明:

我的bfs可能比较复杂,个人习惯,但是觉得理解起来还是比较方便。

完整代码

#include <iostream>
#include<deque>
#include<queue>
#include<stdio.h>
#define CHECK(x, y) (x<wx && x>=0 && y >=0 && y<hy)
using namespace std;
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
char room[1001][1001];
int wx,hy,num,cnt[1000001],way;
int _map[1001][1001];
struct node {int x,y;};
int bfs(int dx,int dy)
{
    num=1;
    queue<node> q;
    node start,next;
    start.x=dx;
    start.y=dy;
    q.push(start);
    while(!q.empty())
    {
        start=q.front();
        q.pop();
        if(room[start.x][start.y]=='1'||room[start.x][start.y]=='#')
        {
            //room[start.x][start.y]='0'+way;
            room[start.x][start.y]='*';
            _map[start.x][start.y]=way;
        for(int i=0;i<4;i++)
        {
            next.x=start.x+dir[i][0];
            next.y=start.y+dir[i][1];
            //cout<<next.x<<" "<<next.y<<endl;
            if(CHECK(next.x,next.y)&&room[next.x][next.y]=='0')
            {
                num++;
                room[next.x][next.y]='.';
                q.push(next);
            }
        }
        }
        else if(room[start.x][start.y]=='0'||room[start.x][start.y]=='.')
        {
            //room[start.x][start.y]='0'+way;
            room[start.x][start.y]='*';
            _map[start.x][start.y]=way;
        for(int i=0;i<4;i++)
        {
            next.x=start.x+dir[i][0];
            next.y=start.y+dir[i][1];
            //cout<<next.x<<" "<<next.y<<endl;
            if(CHECK(next.x,next.y)&&room[next.x][next.y]=='1')
            {
                num++;
                room[next.x][next.y]='#';
                q.push(next);
            }
        }
        }
        //cout<<"size="<<q.size()<<" "<<num<<endl;
    }
    return num;
}
int main()
{
    int n,m,dx,dy;
    cin>>n>>m;
    wx=hy=n;
    for(int i=0;i<n;i++)
        cin>>room[i];
for(way=2;way<=m+1;way++)
{
    cin>>dx>>dy;
    dx=dx-1;
    dy=dy-1;
    if(room[dx][dy]=='0'||room[dx][dy]=='1')
        cnt[way]=bfs(dx,dy);
    //cout<<cnt[room[dx][dy]-'0'];
    printf("%d\n",cnt[_map[dx][dy]]);
    //for(int i=0;i<n;i++)
        //cout<<room[i]<<endl;
}
    return 0;
}