题解 P1141 【01迷宫】

· · 题解

怎么都是深搜的题解,我一开始还以为广搜是错的……

(DEV-C++:那你还调了那么多次……)

贴代码(思路见注释):

#include<bits/stdc++.h>
using namespace std;
bool mp[1010][1010];
int vis[1010][1010];
int q[1010*1010][2];
/*
手写队列比STL快
q[i][0]表示x坐标
q[i][1]表示y坐标
千万不要用struct
要用就用class
struct在栈中存储,栈空间小 
*/ 

int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};//四个方向扩展 

int tot=1;
int ans[1010*1010];
/*
标记是第几个联通块 
ans[i]保存第i个联通块的大小 
*/
int n,m;
/*
check判断是否在迷宫中,
且没有被访问过
判断是否访问过,只需看
vis[x][y]是不是tot即可 
*/
bool check(int x,int y)
{
    if (vis[x][y]==tot) return false;
    if (x<1 or x>n) return false;
    if (y<1 or y>n) return false;
    return true;
}
void bfs(int x,int y)
{
    int head=1,tail=1;
    q[tail][0]=x;
    q[tail][1]=y;
    vis[x][y]=tot; 
    tail++;
    //x,y入队 
    int cnt=1;//计数菌
    /*
    计数君初始为1,因为算上了
    传进来的x,y 
    */ 
    while(head<tail)
    {
        int hx=q[head][0];
        int hy=q[head][1];
        //hx,hy取队首,即q[head] 
        for(int i=0;i<4;i++)
        {
            int tx=hx+dx[i];
            int ty=hy+dy[i];
            //队列扩展 
            if (check(tx,ty) and mp[tx][ty]!=mp[hx][hy])
            {
                q[tail][0]=tx;
                q[tail][1]=ty;
                vis[tx][ty]=tot;//标记联通块 
                tail++;
                cnt++;//计数菌++ 
            }
        }
        head++;
    }
    ans[tot]=cnt;//标记第tot个联通块 
    tot++;
}
int main()
{
    memset(vis,-1,sizeof(vis));
    //记得初始化 
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        char tmp[1010];
        scanf("%s",tmp+1);//从1开始 
        for(int j=1;j<=n;j++)
        {
            mp[i][j]=tmp[j]-'0';
        }
    }
    while(m--)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        int tmp=vis[x][y];//联通块编号 
        if (tmp==-1)//说明这个联通块没有被BFS过 
        {
            bfs(x,y);
            //那就BFS一遍 
            printf("%d\n",ans[vis[x][y]]);
        }
        else//被算过,就直接输答案 
        {
            printf("%d\n",ans[vis[x][y]]);
        }
    } 
    exit(0);
}