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;
}