[CF877D] Olya and Energy Drinks

Description

有一 (N imes M) 的迷宫,# 是墙,. 是路,一秒钟可以向四个方向中的一个移动 (1 sim k) 步,求从起点到终点的最短时间。(N,M,k le 1000)

Solution

正常 BFS 即可解决,关键是考虑到每个点只会入队一次,这样保证了时间复杂度。

主要是要注意一下几个剪枝条件。

#include <bits/stdc++.h>
using namespace std;

#define int long long 
const int N = 1005;

const int di[4] = {0,0,1,-1};
const int dj[4] = {1,-1,0,0};

int n,m,k;
char a[N][N];
int vis[N][N],f[N][N];

int check(int i,int j)
{
    return i>0 && j>0 && i<=n && j<=m;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++) cin>>a[i]+1;
    int x1,y1,x2,y2;
    cin>>x1>>y1>>x2>>y2;
    queue <pair<int,int>> que;
    memset(f,0xff,sizeof f);
    que.push({x1,y1});
    f[x1][y1]=0;
    vis[x1][y1]=1;
    while(!que.empty())
    {
        int pi=que.front().first,pj=que.front().second;
        que.pop();
        if(pi==x2 && pj==y2)
        {
            cout<<f[x2][y2]<<endl;
            return 0;
        }
        for(int d=0;d<4;d++)
        {
            for(int l=1;l<=k;l++)
            {
                int ni=pi+di[d]*l,nj=pj+dj[d]*l;
                if(a[ni][nj]=='#') break;
                if(!check(ni,nj)) break;
                if(f[ni][nj]!=-1 && f[ni][nj]<=f[pi][pj]) break;
                if(f[ni][nj]!=-1 && f[ni][nj]<=f[pi][pj]+1) continue;
                if(check(ni,nj) && vis[ni][nj]==0)
                {
                    vis[ni][nj]=1;
                    f[ni][nj]=f[pi][pj]+1;
                    que.push({ni,nj});
                }
                if(ni==x2 && nj==y2)
                {
                    cout<<f[x2][y2]<<endl;
                    return 0;
                }
            }
        }
    }
    cout<<f[x2][y2]<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/mollnn/p/13866127.html