当青训营遇上码上掘金---寻友之旅

72 阅读2分钟

当青训营遇上码上掘金

寻友之旅

题目描述

小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K ,并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走) 请帮助小青通知小码,小青最快到达时间是多久?

输入格式:

两个整数 N 和 K

输出格式:

小青到小码家所需的最短时间(以分钟为单位)

数据范围

0N,K1e50≤N,K≤1e5

样例

输入样例:

5 17

输出样例:

4

本题其实就是Catch That Cow

解法:bfs求最短路 当所有边的权重为1时,可以使用bfs求最短路,有三种情况,每次将三种情况加入到队列中即可,加入之前需要判断一下是否越界与是否重复

一些可以优化的点:

  1. 零以后的点直接忽略即可,零之后的点除了+1均无法达到正数,而由+1重新回到正数的路径一定大于之前在相同点的距离
  2. 不难发现,如果一个数大于k,则只能选择从t走到t−1的方法。所以我们可以判断一下,t是否大于k。如果大于,则只执行从t走到t−1。当然,我们还可以在开始判断一下,如果是,则直接输出n−k
#include<bits/stdc++.h>

using namespace std;

const int N = 2e5+10;
int st[N];

bool check(int now) {
    if(now < 0 || now > 1e5 || st[now] != 0) return false;
    return true;
}

int main() {
    int n,k;
    cin >> n >> k;
    queue<int> q;
    q.push(n);
    int now = -1;
    while(now != k) {
        now = q.front();
        q.pop();
        if(check(now-1)) {
            q.push(now-1);
            st[now-1] = st[now] + 1;
        }
        if(check(now+1)) {
            q.push(now+1);
            st[now+1] = st[now] + 1;
        }
        if(check(now*2)) {
            q.push(now*2);
            st[now*2] = st[now] + 1;
        }
    }
    cout << st[k] << endl;
    return 0;
}