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;
}
posted @ 2021-04-10 12:16  violet_holmes  阅读(59)  评论(0编辑  收藏  举报