题目
农夫约翰已被告知逃亡牛的位置,并希望立即抓住她。他开始于一个点N(0≤ N≤100,000)和牛是在点K (0≤ K≤100,000),他们在同一条线上。农夫约翰有两种交通方式:步行和乘车。
- 行走:约翰可以在一分钟内从任意点X移动到X -1或X + 1 点
- 乘车:约翰可以在一分钟内从任意点X移动到点2× X
如果母牛不知道它的追赶,根本不动,那么农夫约翰需要多长时间才能找回它?
样例
样例输入
5 17
样例输出
4
解题思路
三叉树:广度优先。从根节点往下遍历,满足条件就加入队列中,同时记录每条路径的长度,即树的高度。等到发现一条可行路径后,该路径的长度或者该树的高度就是走过的步数
AC代码
#include <iostream>
#include <queue>
using namespace std;
int N, K;
int visit[100001];
int height[1000001];
queue<int> q;
int bfs(int N, int K)
{
//如果开始点在终点右边,则只能通过每次倒退一步的方法到达终点,即需要N-K步
if (N >= K)
return N - K;
//当前位置、下一步的位置
int now, next;
//当前位置进队列
q.push(N);
height[N] = 0;
//标记已走过的当前位置
visit[N] = 1;
while (!q.empty())
{
//取出当前的节点,从这个节点开始搜索
now = q.front();
q.pop();
//在每一个结点都朝三个方向搜索
for (int i = -1; i <= 1; i++)
{
//如果越界或者判重没通过,也不用回溯,因为next初值为0,在每次循环中也是实时更新的;head也会不用管,用为head是从队列中出来的,在for循环里没有被赋值,不会发生改变
if (i != 0)
next = now + i;
else
next = now * 2;
//如果越界或者重复,则放弃这条路径
if (next >= 0 && next <= 100001 && visit[next] == 0)
{
q.push(next);
// cout<<next<<" ";
//树的高度加1,即路径长度加1
height[next] = height[now] + 1;
// cout<<height[next]<<endl;
//对走过的点进行标记,很重要。
visit[next] = 1;
}
//如果某一步到达终点,则从根节点到这一个节点的树的高度(即长度)就是走过的步数
if (next == K)
return height[next];
}
}
}
int main()
{
int N, K;
cin >> N >> K;
cout << bfs(N, K) << endl;
}