3060 抓住那头奶牛 USACO
时间限制: 1 s
空间限制: 16000 KB
题目等级 : 黄金 Gold
题解
题目描述 Description
农夫约翰被告知一头逃跑奶牛的位置,想要立即抓住它,他开始在数轴的N 点(0≤N≤100000),奶牛在同一个数轴的K 点(0≤K≤100000)。约翰有两种移动方式:1 分钟内从x 点移动到x+1 或x-1;1 分钟内从x 点移动到2x。假设奶牛不会移动,约翰抓住它需要多少时间?
输入描述 Input Description
一行两个整数N 和K,用空格隔开。
输出描述 Output Description
约翰抓住它需要的最少时间。
样例输入 Sample Input
5 17
样例输出 Sample Output
4
思路:
BFS + 队列
每到下一个的点 就把三种情况执行一次 更新状态 将所有可能状态入队
因为BFS按层遍历的性质,第一次访问到答案的时候一定是最优的
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
const int MAXN = 100005;
using namespace std;
queue<int> q;
int step[MAXN]; //跟随数组,记录步数
bool vis[MAXN];
int n,k,next,head;
int bfs()
{
q.push(n);
step[n]=0;
vis[n]=1;
while(!q.empty())
{
head=q.front();
q.pop();
//分三个方向BFS
for(int i=0; i<3 ;i++)//对其中一种情况一搜到底。。记录所有路径
{
if(i==0) next=head-1;
else if(i==1) next=head+1;
else next=head*2;
if(next > MAXN || next<0 ) continue; //必须先判断,不然会RE,数组越界了
if(!vis[next])
{
q.push(next);
step[next]=step[head]+1;//前一条路径数目,对应的走过的路程,即为当前的路程数
vis[next]=1;
}
if(next==k) return step[next];//广搜的特性,返回的第一个一定是最短的路径
}
}
}
int main()
{
memset(vis,0,sizeof(vis));
scanf("%d%d",&n,&k);
if(n>=k)
{
printf("%d",n-k);
}
else
{
printf("%d",bfs());
}
return 0;
}