[CF1063B] Labyrinth

给定一个 (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;
}

原文地址:https://www.cnblogs.com/mollnn/p/12584366.html