[宽度优先搜索] Acwing 1100. 抓住那头牛

农夫知道一头牛的位置,想要抓住它。

农夫和牛都位于数轴上,农夫起始位于点 N,牛位于点 K。

农夫有两种移动方式:

从 X 移动到 X−1 或 X+1,每次移动花费一分钟
从 X 移动到 2∗X,每次移动花费一分钟
假设牛没有意识到农夫的行动,站在原地不动。

农夫最少要花多少时间才能抓住牛?

输入格式

共一行,包含两个整数N和K。

输出格式

输出一个整数,表示抓到牛所花费的最少时间。

数据范围

0≤N,K≤105

输入样例:

5 17

输出样例:

4

思路分析

宽度优先队列最短路模型,就是更新d数组,记录各个点到起点的距离,当发现终点的时候,就把这个值返回。所以这个bfs的根本作用就是更新这个d数组,更新d数组的作用是找到终点d的值,也就是最短的距离。入队的同时更新d数组,出队是为了入队。

AC代码

#include
using namespace std;
const int maxn=2e5+10;

int n,k; 
int d[maxn];

int bfs(){
	memset(d,-1,sizeof d);
	int q[maxn],tt=-1,hh=0;
	q[++tt]=n,d[n]=0;
	
	while(tt>=hh){
		int t=q[hh++];
		if(t==k)	return d[t];
		if(t*2<=2*k&&d[t*2]==-1){
			d[t*2]=d[t]+1,q[++tt]=t*2;
		}
		if(t+1<=2*k&&d[t+1]==-1){
			d[t+1]=d[t]+1,q[++tt]=t+1;
		}
		if(t-1>=0&&d[t-1]==-1){
			d[t-1]=d[t]+1,q[++tt]=t-1;
		}
	}
	return -1;
}

int main(){
	scanf("%d %d",&n,&k);
	printf("%d",bfs());
	return 0; 
}

要点分析

要注意边界,这个题目看似没有边界,世界上边界是[0,2k]。因为n和k都是非负整数,而且当这个人的起点在终点右边的时候,不可能跑到终点左边,所以是不可能小于0的;
当我在终点的右边的时候,我不可能继续+1或者
2,因为这样做了还得回来,所以我+1或2只能在k的左边。所以不可能超过2k。所以就确定了边界。不确定边界的话,就会一直有点进队列,就会死循环下去。

你可能感兴趣的:(#,搜索)