题解
⭐:若图中边权全部为(1),BFS即可在(O(n+m))的时间中求出单源最短路。
BFS+剪枝就可以啦(☆▽☆)
BFS:对于每个位置,向上下左右4个方向拓展长度(k),直接搜索。
剪枝:在拓展过程中(当前拓展到位置((x,y))),只要发现一个无法更新的位置((tx,ty))((dis[tx][ty]<dis[x][y]+1),(dis[i][j])表示((i,j))到起点的最小操作数),便跳出拓展。正确性:因为之后拓展的(dis)一定(le dis[tx][ty]+1),所以也(le dis[x][y])。时间:因为所有已经搜索到的节点((i,j))一定满足(dis[i][j]le dis[x][y]),所以搜索到的节点无法进入拓展循环,时间复杂度为(O(nk))。
AC代码
#include<bits/stdc++.h>
#define mp make_pair
using namespace std;
const int N=1010,inf=0x3f3f3f3f;
char a[N][N];
int sx,sy,ex,ey,n,m,k,dis[N][N];
int dx[5]={1,0,-1,0},dy[5]={0,1,0,-1};
bool vis[N][N];
queue<pair<int,int> > q;
bool ok(int x,int y)
{return 1<=x && x<=n && 1<=y && y<=m && a[x][y]=='.';}
void bfs()
{
memset(dis,0x3f,sizeof(dis));
q.push(mp(sx,sy)); dis[sx][sy]=0;
while(!q.empty())
{
int x=q.front().first,y=q.front().second; q.pop();
for(int i=0;i<4;i++)
{
for(int j=1;j<=k;j++)
{
int tx=x+j*dx[i],ty=y+j*dy[i];
if(!ok(tx,ty) || dis[tx][ty]<dis[x][y]+1) break;
if(dis[tx][ty]==inf)
{dis[tx][ty]=dis[x][y]+1; q.push(mp(tx,ty));}
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++) scanf("%s",a[i]+1);
scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
bfs();
if(dis[ex][ey]==0x3f3f3f3f) printf("-1");
else printf("%d",dis[ex][ey]);
return 0;
}