CF877D Solution
题解
⭐:若图中边权全部为\(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;
}