给定一个 (n imes m) 地图,每个格子为空地或墙,你从一个位置开始,四连通移动,向上向下次数不限,向左最多 (x) 次,向右最多 (y) 次,问能到达多少个格子
Solution
如果只有一个方向有代价,那么简单 BFS 即可
然而这里两个方向都有代价,但是点 ((r,c) o (i,j)) 的横坐标差是确定的,换言之,如果设向左走了 (a) 步,那么向右走的步数就是 (i-r+a)
于是我们只对向左的边设代价即可,最终在考虑 ((r,c) o (i,j)) 的过程时,同时要求 $a leq x $ 和 $ j-c+a leq y$ 即可
#include <bits/stdc++.h>
using namespace std;
const int N = 2005;
const int di[4] = {1,-1,0,0}, dj[4] = {0,0,1,-1};
int n,m,r,c,x,y,f[N][N],v[N][N];
char a[N][N];
struct point {int i,j;};
int ok(int i,int j) {
if(i>=1 && j>=1 && i<=n && j<=m && a[i][j]=='.') return 1;
return 0;
}
signed main() {
ios::sync_with_stdio(false);
cin>>n>>m>>r>>c>>x>>y;
for(int i=1;i<=n;i++) {
cin>>a[i]+1;
}
memset(f,0x3f,sizeof f);
f[r][c]=0;
deque <point> q;
q.push_back({r,c});
while(q.size()) {
int i=q.front().i, j=q.front().j;
q.pop_front();
for(int k=0;k<4;k++) {
int ni=i+di[k],nj=j+dj[k];
if(ok(ni,nj)) {
if(k<3) {
f[ni][nj]=min(f[ni][nj],f[i][j]);
if(v[ni][nj]<2) {
v[ni][nj]=2;
q.push_front({ni,nj});
}
}
else {
f[ni][nj]=min(f[ni][nj],f[i][j]+1);
if(!v[ni][nj]) {
v[ni][nj]=1;
q.push_back({ni,nj});
}
}
}
}
}
int ans=0;
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
if(f[i][j]<=x && j-c+f[i][j]<=y) ++ans;
}
}
cout<<ans;
}