思路
:
vis前两维记录坐标,第三维记录是否用过药水,然后bfs即可,注意数组越界问题。
注意如果一个点用过了药水,则他所有可以扩展的点的状态都是喝过的,就是flag=1,不能再用药水了,不用再搜。这个点没用过的话,它扩展的点的既有不用的(上下左右),也有用药水的,都要入队。
Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll MAXN = 2010;
struct point{
long long x1,y1,step,flag;
}start;
queue<point> dl;
ll dx[4] = {0,0,1,-1};
ll dy[4] = {1,-1,0,0};
char mp[MAXN][MAXN];
bool v[MAXN][MAXN][2];
ll n,m,f,d,r;
int main() {
cin>>n>>m>>d>>r;
for(ll i=1;i<=n;i++){
for(ll j=1;j<=m;j++){
cin>>mp[i][j];
}
}
start.x1=1;
start.y1=1;
start.step=1;
start.flag=0;
dl.push(start);
v[1][1][0] = 1;
while (!dl.empty()) {
point head = dl.front();
dl.pop();
if(head.x1==n&&head.y1==m) {
cout<<head.step-1<<endl;
return 0;
}
f=head.flag;
for (ll i=0;i<4;i++) {
ll tx = dx[i]+head.x1;
ll ty = dy[i]+head.y1;
if (tx>0&&tx<=n&&ty>0&&ty<=m&&mp[tx][ty]!='#'&&v[tx][ty][f]==0) {
v[tx][ty][f] = 1;
point temp;
temp.x1 = tx;
temp.y1 = ty;
temp.flag=f;
temp.step = head.step + 1;
dl.push(temp);
}
}
ll tx = head.x1+d, ty = head.y1+r;
if (tx>0&&tx<=n&&ty>0&&ty<=m&&f==0&&!v[tx][ty][1]&&mp[tx][ty]!='#') {
v[tx][ty][1] = 1;
point temp;
temp.x1 = tx;
temp.y1 = ty;
temp.flag=1;
temp.step = head.step + 1;
dl.push(temp);
}
}
cout<<-1<<endl;
return 0;
}