题目:
农夫知道一头牛的位置,想要抓住它。农夫和牛都于数轴上 ,农夫起始位于点 N(0<=N<=100000) ,牛位于点 K(0<=K<=100000) 。农夫有两种移动方式: 1、从 X移动到 X-1或X+1 ,每次移动花费一分钟 2、从 X移动到 2*X ,每次移动花费一分钟 假设牛没有意识到农夫的行动,站在原地不。最少要花多少时间才能抓住牛?
Input
一行: 以空格分隔的两个字母: N 和 K
Output
一行: 农夫抓住牛需要的最少时间,单位分钟
Sample Input
5 17
Sample Output
4
Hint
农夫使用最短时间抓住牛的方案如下: 5-10-9-18-17, 需要4分钟.
分析与解答
由于无法确定深度,因此用bfs广搜,bfs不需要回溯,是一层一层推进,一直到最后的解
这题有三种情况,后退一步,前进一步,前进二倍当前距离,那我们就层次遍历,每层输入到队列里,输完了就把上一层pop掉,就是不断遍历并且查找,遇到最终结果return并输出time即可
为了减小时间,我们需要判重,每次只入那些曾经没出现过的数。
这一类bfs具体怎么实现,就是先建一个队列,然后把第一个数push里面,只要队列不空,就一直对队列进行出队入队操作。需要有两个变量 m,next;m存的是根结点,每次循环最初需要把他取出,next存的是由根结点+1-1*2从而形成的子结点,我们存子结点时注意判重,不重复我们就push next,并且标记。注意每次操作完之后我们都要检查一下是不是满足最终的结果,如果满足我们直接return就行
代码参考:https://blog.csdn.net/qq_38620461/article/details/78445374
#include<bits/stdc++.h>
using namespace std;
int to[2]={1,-1};
int a,b,sum;
int vis[100000];
struct place
{int x,time;
};
int check(place k)
{if(k.x<0||k.x>100000||vis[k.x]==1)return 0;return 1;
}
int bfs(place n)
{place m,next;queue<place>w;w.push(n);while(!w.empty()) {m=w.front();w.pop();if(m.x==b)return m.time;for(int i=0;i<2;i++){next.x=m.x+to[i];next.time=m.time+1;if(next.x==b)return next.time;if(check(next)){w.push(next);vis[next.x]=1;}}next.x=m.x*2;next.time=m.time+1;if(next.x==b)return next.time;if(check(next)){w.push(next);vis[next.x]=1;}}return 0;
}
int main()
{int i,j,t;place x1;while(~scanf("%d %d",&a,&b)){memset(vis,0,sizeof(vis));x1.x=a;x1.time=0;vis[x1.x]=1;sum=0;sum=bfs(x1);printf("%d\n",sum);}return 0;
}