题目地址:
https://www.acwing.com/problem/content/description/1102/
农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点
N
N
N,牛位于点
K
K
K。农夫有两种移动方式:
从
X
X
X移动到
X
−
1
X−1
X−1或
X
+
1
X+1
X+1,每次移动花费一分钟;
从
X
X
X移动到
2
X
2X
2X,每次移动花费一分钟。
假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?
输入格式:
共一行,包含两个整数
N
N
N和
K
K
K。
输出格式:
输出一个整数,表示抓到牛所花费的最少时间。
数据范围:
0
≤
N
,
K
≤
1
0
5
0≤N,K≤10^5
0≤N,K≤105
思路是BFS。可以做适当优化,例如,如果当前位置 x x x是大于等于 k k k的,那么拓展的时候不必拓展 x + 1 x+1 x+1和 2 x 2x 2x,因为拓展完了还得减 1 1 1向左走,白白耗费步数;此外,也不用拓展负数,因为拓展完了还得加 1 1 1向右走,也白白耗费步数。代码如下:
#include <iostream>
#include <queue>
using namespace std;
const int N = 2e5 + 10;
int n, k;
queue<int> q;
bool st[N];
int bfs(int n, int k) {
if (n == k) return 0;
int res = 0;
q.push(n);
st[n] = true;
while (!q.empty()) {
res++;
int size = q.size();
for (int i = 0; i < size; i++) {
int t = q.front();
q.pop();
if (t == k) return res;
// 不拓展负数
if (!st[t - 1] && t - 1 >= 0) {
if (t - 1 == k) return res;
q.push(t - 1);
st[t - 1] = true;
}
// 只有t < k的时候才拓展t + 1和2 * t
if (t < k) {
if (!st[t + 1]) {
if (t + 1 == k) return res;
q.push(t + 1);
st[t + 1] = true;
}
if (!st[t * 2]) {
if (t * 2 == k) return res;
q.push(t * 2);
st[t * 2] = true;
}
}
}
}
// 显然题目一定有解,所以这一行是走不到的
return -1;
}
int main() {
cin >> n >> k;
cout << bfs(n, k) << endl;
return 0;
}
时空复杂度要看具体数据。