【ACWing】1100. 抓住那头牛

题目地址:

https://www.acwing.com/problem/content/description/1102/

农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点 N N N,牛位于点 K K K。农夫有两种移动方式:
X X X移动到 X − 1 X−1 X1 X + 1 X+1 X+1,每次移动花费一分钟;
X X X移动到 2 ∗ X 2∗X 2X,每次移动花费一分钟。
假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?

输入格式:
共一行,包含两个整数 N N N K K K

输出格式:
输出一个整数,表示抓到牛所花费的最少时间。

数据范围:
0 ≤ N , K ≤ 1 0 5 0≤N,K≤10^5 0N,K105

思路是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;
}

时空复杂度要看具体数据。

猜你喜欢

转载自blog.csdn.net/qq_46105170/article/details/114562678