(洛谷)【P1141】01迷宫 [广度搜索][高性能]

首先,这篇文章本是我原创,代码也是我自己写的,但是由于洛谷里有相似的题解,思路和我几乎相同,所以我把这篇文章定性为搬运。

原题目:洛谷P1141


——————分割线——————

这道题属于普通的广度搜索,我本来用的暴算,但是除了前几个AC,都是超时,所以肯定不能对每一个数据都来一次搜索(最大迷宫为1000×1000,最多查询点数为1000000,所以暴算的话最大搜索次数为1000000000000)。因此,需要用一种算法来进行优化。


审视这道题,可以发现:如果一个点可以到达n个格子,那么对于这n个格子中的每一个,其可以到达的格子数都是n,因为它们构成了一个联通块。所以只要知道这个联通块的答案,就可以知道每个点的答案。


所以我想到了用染色原理,先全部广搜,在过程中将每个联通块染成不同的颜色,然后将这种颜色所对应的答案存储到一个数组之中,输入点的坐标的时候,只需要查询这个点的颜色,就可以根据数组输出答案。


直接上代码:

#include<iostream>
using namespace std;
int mig[1001][1001], color[1001][1001];//color就是每个点的颜色
int trans[1000001];//trans是每种颜色对应的答案
int coloring=1, ans=0;//将所有格子的颜色初始化为0,第一个联通块的颜色设为1,每一次循环之后++coloring
int m, n;
void searching(int x, int y) {
     ++ans;
     color[x][y]=coloring;//染色
     if((x+1>0) && (x+1<=n) && (mig[x][y]+mig[x+1][y]==1) && (color[x+1][y]==0)) {searching(x+1,y);}
     if((x-1>0) && (x-1<=n) && (mig[x][y]+mig[x-1][y]==1) && (color[x-1][y]==0)) {searching(x-1,y);}
     if((y+1>0) && (y+1<=n) && (mig[x][y]+mig[x][y+1]==1) && (color[x][y+1]==0)) {searching(x,y+1);}
     if((y-1>0) && (y-1<=n) && (mig[x][y]+mig[x][y-1]==1) && (color[x][y-1]==0)) {searching(x,y-1);}//查询部分
     }
int main() {
    cin >> n >> m;
    string pan[n+1];
    for(int i=1; i<=n; i++) {
            cin >> pan[i];
            }
    for(int i=1; i<=n; i++) {
            for(int j=1; j<=n; j++) {
                    color[i][j]=0;
                    mig[i][j]=pan[i][j-1]-'0';
                    }
	    }//转换迷宫
    for(int i=1; i<=n; i++) {
            for(int j=1; j<=n; j++) {
                    if(color[i][j]==0) {//如果color[i][j]不为0,再广搜,不然会重复计算浪费时间
                                       searching(i,j);
                                       trans[coloring]=ans;//导入答案
                                       ans=0;
                                       ++coloring;//换颜色
                                       }
                    }
            }
    int a,b;
    for(int i=1; i<=m; i++) {
            cin >> a >> b;
            cout << trans[color[a][b]];
            }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值