寻友之旅

60 阅读1分钟

题意:

给定正整数n,kn, k,代表两个人的位置。其中位置nn可以如下变化:

  • 变成n+1n+1
  • 变成n1n-1
  • 变成n×2n \times 2

问最少变化几次,nn能够变成kk

思路:

看到这个题,我先想到能不能dpdp求解,但是这里有个n1n-1的操作,意味着这样无法保证dpdp需要的“无后效性”。

所以就只好考虑搜索了,这里我采用了bfsbfs,因为bfsbfs是一层一层的遍历,而dfsdfs是递归到底层,虽然总体来说复杂度是一样的,但是dfsdfs容易爆栈,因为这题的n,kn,k达到了1e51e5的级别。

于是就可以开一个数组,记录走到这个点花了多少步,同时这个数组也有标记走没走过的作用。然后就是一步步的bfsbfs拓展了。

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 5, mod = 998244353;
int f[N];
void solve()
{
    int n, k;
    cin >> n >> k;
    
    queue<int> q;
    q.push(n);
    f[n] = 1;

    while(!q.empty()){
        int x = q.front();
        q.pop();
        if (x == k) break;

        if (!f[x + 1]){
            q.push(x + 1);
            f[x + 1] = f[x] + 1;
        }
        if (x - 1 >= 0 && !f[x - 1]){
            q.push(x - 1);
            f[x - 1] = f[x] + 1;
        }
        if (x * 2 <= 2 * k && !f[2 * x]){
            q.push(x * 2);
            f[2 * x] = f[x] + 1;
        }
    }
    cout << f[k] - 1;
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int tt = 1;
    // cin >> tt;
    while (tt--) solve();
    return 0;
}