洛谷 P1141 01迷宫

呐,你想成为什么颜色?                            ——《樱花庄的宠物女孩》

题目:https://www.luogu.org/problem/P1141

花了点时间把这题搞定,看到标签中的“高性能”后真的吓一跳,最怕这种题了——

因为它永远永远肯定是要优化的。

而我最不会的就是优化。

于是一开始,我就是用暴力bfs来搞的,然后抱着试一试的心态交了一下,果不其然炸三个点,TLE了。

然后想着改进方式,仔细一想,好像一次bfs后会把一些数组标记掉,让它无法重复走;而且这些在同一次标记过的点中,无论从那个点出发,走到的点数是一样的!

这么一想,似乎就明了了——

联通块!!!

你以为我会告诉你我其实一开始没想到的,是看了题解才知道的吗

其实还有一件事,我习惯在bfs时,在开头用memset重置一下,但这题因为要重置的数组太大(1000000),每次搜索重置,绝对会炸掉,因此我在用了联通块后还是TLE掉两个点,蓝瘦。

好了,那么废话不说,上代码:

#include<bits/stdc++.h>//这题连通图思想很关键 
using namespace std;
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,-1,1};
int n,m,ans=1;
int sx,sy;
int sum[1000005];
char a[1005][1005];
int b[1005][1005];//把它变成一个连通图 ,同一连通图中值相等 
int h[1000005][4];
int head=0,tail=0,tu=0;//tu用来记录连通图数量 
void bfs(int x,int y)
{
    tu++;
    head=0;tail=1;ans=1;
    h[1][1]=x,h[1][2]=y,h[1][3]=int(a[x][y]);
    b[x][y]=tu;
    while(head<tail)
    {
        head++;
        for(int i=1;i<=4;i++)
        {
            int xx=dx[i]+h[head][1];
            int yy=dy[i]+h[head][2];
            if(!b[xx][yy]&&xx>=0&&xx<n&&yy>=0&&yy<n&&int(a[xx][yy])!=h[head][3])
            {
                tail++;
                h[tail][1]=xx;
                h[tail][2]=yy;
                h[tail][3]=int(a[xx][yy]);
                b[xx][yy]=tu;
                ans++;
            }
        }
    }
    sum[tu]=ans;
}
int main()
{
    memset(b,0,sizeof(b));
    memset(h,0,sizeof(h));
    //放搜索外面,不然每次搜索都要重置一遍很费时间的
    //毕竟h数组很大啊 
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
      scanf("%s",a[i]);
    for(int i=1;i<=m;i++)
    {
       scanf("%d%d",&sx,&sy);
       sx--;sy--;
       if(b[sx][sy]==0) bfs(sx,sy);
       printf("%d\n",sum[b[sx][sy]]);
       //因为要算的包括自己,所以要加1 
    }
    return 0;
}

 

posted @ 2019-08-31 17:05  crxscp-173  阅读(171)  评论(0编辑  收藏  举报