Luogu P3818 小A和uim之dark♂逃离 Ⅱ

沉迷分层图无法自拔......

这道题,首先一看,不就是个BFS走迷宫嘛,一本通上都有讲过

然后,诶怎么还有上一次的魔液(诶原来魔液是干这个用的

然后就想到,「诶,魔液只能用一次......那就用0/1表示没有用/用过,就行了吧」

然后就开始......

建图......(诶我真是丧心病狂)

用三个数字x,y,z表示某个点的坐标,z=0表示在第一层(没有喝过),z=1表示在第二层(喝过了)

在原有两层正常图的基础上,喝魔液相当于连一条从图层0到图层1的,起点为 $ (x,y,0) $ ,终点为 $ (x+d,y+r,1) $ 的边。

建完图之后从起点开始跑一遍SPFA,取 $ min(d[n][m][0],d[n][m][1]) $ 即为答案。

思路出来了,十分钟敲完了代码,兴高采烈拿去试样例......结果第三个样例WA了,输出13正解21

(话说这道题的样例还是很良心的,不像某些题的样例不具有特殊性,查不出错)

扫描二维码关注公众号,回复: 3063473 查看本文章

为什么会少呢......肯定是抄近路了

于是便开始输出中间结果调试

果不其然,数组从0到n,0到m,而出发点是在(1,1),我特判没写好,导致可以从x=0或y=0的「不存在的地方」抄近路过去

形象化来说就是走地图边偷家

改了之后就一遍A了


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

int a[1005][1005];
int n,m,d,r;

struct node{
    int x,y,z;
    node(int x=0,int y=0,int z=0):
        x(x),y(y),z(z){
            
        }
};

bool ok(int x,int y){
    if(x<1 or x>n or y<1 or y>m)return 0;
    return 1;
}
int f[1005][1005][2];

bool vis=0;
void bfs(){
    bool inq[1005][1005][2];
    memset(inq,0,sizeof inq);
    memset(f,0x3f3f,sizeof f);
    queue<node>q;
    f[1][1][0]=0;
    q.push(node(1,1,0));
    inq[1][1][0]=1;
    while(!q.empty()){
        node u=q.front();
        int x=u.x,y=u.y,z=u.z;
        inq[x][y][z]=0;
        q.pop();
        if(x<1 or x>n or y<1 or y>m)continue;
        if(ok(x+1,y) and f[x+1][y][z]>f[x][y][z]+1 and !a[x+1][y]){
            f[x+1][y][z]=f[x][y][z]+1;
            if(x+1==n and y==m)vis=1;
            if(!inq[x+1][y][z]){
                inq[x+1][y][z]=1;
                q.push(node(x+1,y,z));
            }
        }
        if(ok(x-1,y) and f[x-1][y][z]>f[x][y][z]+1 and !a[x-1][y]){
            f[x-1][y][z]=f[x][y][z]+1;
            if(x-1==n and y==m)vis=1;
            if(!inq[x-1][y][z]){
                inq[x-1][y][z]=1;
                q.push(node(x-1,y,z));
            }
        }
        if(ok(x,y+1) and f[x][y+1][z]>f[x][y][z]+1 and !a[x][y+1]){
            f[x][y+1][z]=f[x][y][z]+1;
            if(x==n and y+1==m)vis=1;
            if(!inq[x][y+1][z]){
                inq[x][y+1][z]=1;
                q.push(node(x,y+1,z));
            }
        }
        if(ok(x,y-1) and f[x][y-1][z]>f[x][y][z]+1 and !a[x][y-1]){
            f[x][y-1][z]=f[x][y][z]+1;
            if(x==n and y-1==m)vis=1;
            if(!inq[x][y-1][z]){
                inq[x][y-1][z]=1;
                q.push(node(x,y-1,z));
            }
        }
        if(ok(x+d,y+r) and z==0 and f[x+d][y+r][1]>f[x][y][0]+1 and !a[x+d][y+r]){
            f[x+d][y+r][1]=f[x][y][0]+1;
            if(x+d==n and y+r==m)vis=1;
            if(!inq[x+d][y+r][1]){
                inq[x+d][y+r][1]=1;
                q.push(node(x+d,y+r,1));
            }
        }
    }
}
int main(){
    scanf("%d%d%d%d",&n,&m,&d,&r);
    for(int i(1);i<=n;i++){
        for(int j(1);j<=m;j++){
            char in;cin>>in;
            if(in=='#')a[i][j]=1;
        }
    }
    bfs();
    if(!vis){
        cout<<-1;
        return 0;
    }
    printf("%d",min(f[n][m][0],f[n][m][1]));
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/soul-M/p/9589972.html