当青训营遇上码上掘金|主题3

66 阅读2分钟

当青训营遇上码上掘金

主题3:寻友之旅(BFS解法)

题面:

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

解法: BFS很经典的一道题目,虽然题面看到过很多个版本,但是一看到题目本质就觉得既视感太强了2333。

变量解释: maxn:最大可能结点(题目条件1e5,再加5防爆)

t[maxn]:到达每个节点的最小时间

队列next:下一个bfs的对象,bfs队列经典用法

广度优先搜索(也称宽度优先搜索,缩写BFS)是连通图的一种遍历策略。它的思想是从一个顶点开始,辐射状地优先遍历其周围较广的区域(一生二,二生三,三生万物……)。从起点开始,经过多轮搜索达到终点,此时记录的轮数就是到终点的最短路程,很多最短路径算法就是基于广度优先的思想成立的。这道题也一样,而且远没有复杂的图那样难办。

总体思路就是从n开始,bfs遍历每个可到达的点。新到达的是当前起点的时间+1,然后把新点放到队列里用于下一轮bfs。

一点细节补充: 这里用memset设成-1而不是0是为了防止n==k的情况,根据是否-1可以根据这个判断这个点到过没有,到过就不更新了。当然设成0然后用一个特判n是否等于k来防止特例也是可以的。 if (2a < maxn && t[2a] == -1)像这个位置要把判断是否超过数组范围放在前面,免得运行错误。

#!/jcode/lang/cpp https://xitu.github.io/jcode-languages/dist/lang-cpp.json

#include<iostream>
#include<utility>
#include<algorithm>
#include<string>
#include<vector>
#include<queue>
#include<sstream>
#include<stack>
#include<string.h>
#include<queue>
#include<unordered_map>
using namespace std;

const int maxn = 100005;
int t[maxn];



int bfs(int &n,int &k)
{
    queue<int> next;
    memset(t, -1, sizeof(t));
    next.push(n);
    t[n] = 0;
    while (!next.empty())
    {
        int a = next.front();
        next.pop();
        if (2*a < maxn && t[2*a] == -1)
        {
            t[2*a] = t[a] + 1;
            if (2*a == k)return t[2*a];
            next.push(2*a);
        }
        if (a + 1 < maxn && t[a + 1] == -1)
        {  
            t[a + 1] = t[a] + 1;
            if (a + 1 == k)return t[a + 1];
            next.push(a + 1);
            
        }
        if (t - 1 >= 0 && t[a - 1] == -1)
        {
            t[a - 1] = t[a] + 1;
            if (a - 1 == k)return t[a - 1];
            next.push(a - 1);
        }
        
    }
    
}

int main()
{   int n, k;
    cin >> n >> k;
    cout << bfs(n,k) << endl;
    return 0;
}