AcWing 4481. 方格探索

根据题意,需要求得:每个可以到达的点,从起点移动过来,需要往右移动的最短距离(x)和往左移动的最短距离(y)
本质是最短路问题,并且可以发现只要求得x或者y中其中一个就可以推出另一个(每个点到起点的横坐标差值是固定的)

可以把整个邻接矩阵看成一个有向图,每个格子与相邻的格子都有一条有向边
dis数组存储从起点到当前点往右移动的最短步数,所以指向右边格子的边权为1,其余都为0
转化成了0/1最短路问题,用双端队列bfs求最短路
最后遍历dis数组,统计满足条件的点的数量 
#include<bits/stdc++.h>
using namespace std;

#define fr first
#define se second

typedef pair<int,int> PII;

const int N = 2010;

int n,m,sx,sy,L,R;

int dis[N][N];
bool st[N][N];

int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
char g[N][N];

void bfs(){
    memset(dis,0x3f,sizeof dis);
    deque<PII> dq;
    dq.push_back({sx,sy});
    dis[sx][sy]=0;
    while(!dq.empty()){
        auto cur=dq.front();
        dq.pop_front();
        if(st[cur.fr][cur.se]) continue;
        st[cur.fr][cur.se];
        for(int i=0;i<4;i++){
            PII to={cur.fr+dx[i],cur.se+dy[i]};
            // cout<<to.fr<<" "<<to.se<<endl;
            if(to.fr && to.se && to.fr<=n && to.se<=m && g[to.fr][to.se]!='*')
                if(dis[to.fr][to.se]>dis[cur.fr][cur.se]+(dy[i]==1?1:0)){
                    dis[to.fr][to.se]=dis[cur.fr][cur.se]+(dy[i]==1?1:0);
                    if(dy[i]==1) dq.push_back(to);
                    else dq.push_front(to);
                }
        }
    }
}

int main(){
    cin>>n>>m>>sx>>sy>>L>>R;
    for(int i=1;i<=n;i++) cin>>g[i]+1;
    
    bfs();
    
    int res=0;
    
    // for(int i=1;i<=n;i++){
    //     for(int j=1;j<=m;j++) cout<<dis[i][j]<<" ";
    //     cout<<endl;
    // }
        
    
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(dis[i][j]<=R && (dis[i][j]-(j-sy))<=L)
                res++;
    cout<<res;
    return 0;
}
posted @ 2022-06-14 01:31  xhy666  阅读(23)  评论(0)    收藏  举报