沉迷分层图无法自拔......
这道题,首先一看,不就是个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
(话说这道题的样例还是很良心的,不像某些题的样例不具有特殊性,查不出错)
为什么会少呢......肯定是抄近路了
于是便开始输出中间结果调试
果不其然,数组从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;
}