抓住那头牛
题目描述
农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点 N
(0 ≤ N ≤ 100000),牛位于点 K
(0 ≤ K ≤ 100000)。农夫有两种移动方式:
- 从
X
移动到X-1
或X+1
,每次移动花费一分钟。 - 从
X
移动到2*X
,每次移动花费一分钟。
假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?
输入
两个整数,N
和 K
。
输出
一个整数,农夫抓到牛所要花费的最小分钟数。
输入样例
5 17
输出样例
4
解决方案
我们可以使用广度优先搜索(BFS)来解决这个问题。BFS 是一种逐层遍历的搜索算法,非常适合用于寻找最短路径。我们使用 pair 来记录当前位置和步数,并使用队列来实现 BFS。
代码讲解
-
输入处理:
- 读取起始位置 n 和目标位置 k。
- 如果 n 等于 k,直接输出
0
并返回。
-
初始化队列和访问数组:
- 使用 queue<pair<int, int>> 来存储位置和步数。
- 使用 vector<bool> visited(100001, false) 来记录已经访问过的位置,防止重复访问。
- 将起始位置和步数(0)存入队列,并标记为已访问:q1.push({n, 0}); visited[n] = true;。
-
BFS 算法:
- 使用
while(!q1.empty())
循环进行广度优先搜索。 - 获取队列的第一个元素的当前位置 t 和步数 step:
int t = q1.front().first; int step = q1.front().second;
。 - 弹出队列的第一个元素:q1.pop()。
- 如果当前位置 t 等于目标位置 k,输出步数并退出:
if(t == k) { cout << step << endl; return 0; }
。 - 将下一步的可能位置加入队列,并标记为已访问:
if(t - 1 >= 0 && !visited[t - 1]){ q1.push({t - 1, step + 1}); visited[t - 1] = true; } if(t + 1 <= 100000 && !visited[t + 1]){ q1.push({t + 1, step + 1}); visited[t + 1] = true; } if(2 * t <= 100000 && !visited[2 * t]){ q1.push({2 * t, step + 1}); visited[2 * t] = true; }
- 使用
通过这种方式,我们可以有效地找到农夫抓到牛所需的最少时间。使用 pair
记录步数,使得 BFS 算法更加简洁和高效。
完整代码实现
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, k;
cin >> n >> k;
if (n == k) {
cout << 0 << endl;
return 0;
}
vector<bool> visited(100001, false);
queue<pair<int, int>> q1;
q1.push({n, 0});
visited[n] = true;
while(!q1.empty()){
int t = q1.front().first;
int step = q1.front().second;
q1.pop();
// 如果找到了目标位置,输出步数并退出
if(t == k){
cout << step << endl;
return 0;
}
// 将下一步的可能位置加入队列,并标记为已访问
if(t - 1 >= 0 && !visited[t - 1]){
q1.push({t - 1, step + 1});
visited[t - 1] = true;
}
if(t + 1 <= 100000 && !visited[t + 1]){
q1.push({t + 1, step + 1});
visited[t + 1] = true;
}
if(2 * t <= 100000 && !visited[2 * t]){
q1.push({2 * t, step + 1});
visited[2 * t] = true;
}
}
return 0;
}