当青训营遇上码上掘金 主题 3:寻友之旅-建图BFS解法

89 阅读2分钟

题干:

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

分析:

分析题干后可以发现这是一道寻找最短路的题目,所以我们可以考虑根据题意建图,随后运用图论寻找最短路的算法解决。根据步行交通方式的描述,不难看出每两个相邻节点都连接着一条无向边,即对于任意节点X,其分别与X-1节点与X+1节点有一条双向边;同时根据公交交通方式的描述,对于任意节点X,其有一条通向2*X的有向边。

对于求最短路径的算法,由于每条边的权重都是一分钟,所以这里我们选择广度优先搜索(BFS)算法即可。具体实现时需注意当乘坐公交时,可能会到达2*X的坐标位置,即我们给节点开的空间内存需大于题目给的1e5。这里我们选择了1e6的空间,但实际上由于终点坐标肯定小于等于1e5,所以如果你所在的位置超过2e5就没有任何意义了,因为其肯定不会是最优解。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef vector<int> vi;
const int N = 1000100;
#define pb push_back
int main()
{
    int n, k;cin>>n>>k;
    vi vis(N, -1);
    queue<int> bfs;
    int res = 0;
    bfs.push(n);
    while(!bfs.empty())
    {
        int len = bfs.size(), flag = 0;
        for(int i = 0; i < len && !flag; i++)
        {
            int idx = bfs.front();bfs.pop();
            vis[idx] = 1;
            if(idx == k)flag = 1;
            if(idx * 2 < N && vis[idx * 2] == -1)bfs.push(idx * 2);
            if(idx + 1 < N && vis[idx + 1] == -1)bfs.push(idx + 1);
            if(idx - 1 >= 0 && vis[idx - 1] == -1)bfs.push(idx - 1);
        }
        if(flag)break;
        res++;
    }
    cout<<res;
    return 0;
}