「青训营 X 码上掘金」寻友之旅题解

111 阅读2分钟

当青训营遇上码上掘金,让我们通过主题3 —— 寻友之旅来开启这趟旅程。

题目

主题 3:寻友之旅

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

请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)

分析

这道题很明显是通过 BFS 进行搜索,因为 N 与 K 的数据范围都不算太大,所以爆搜肯定是在时间范围内的。

#include <iostream>
#include <queue>
#include <vector>

using namespace std;
const int NN = 100010;

int bfs(int N, int K) {
    int M = max(N, K) + 11;
    queue<int> q;
    vector<int> d(M, NN);
    vector<bool> v(M, false);

    d[N] = 0;
    q.push(N);
    v[N] = true;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        if (d[u] + 1 >= d[u - 1]) {
        } else {
            if (u <= 0) {}
            else {
                d[u - 1] = d[u] + 1;
                if (v[u - 1]) {}
                else {
                    q.push(u - 1);
                    v[u - 1] = true;
                }
            }
        }
        if (d[u + 1] > d[u] + 1)
            if (u < M - 1) {
                d[u + 1] = d[u] + 1;
                if (v[u + 1]) {}
                else {
                    q.push(u + 1);
                    v[u + 1] = true;
                }
            } else {}
        if (d[2 * u] > d[u] + 1) {
            if (2 * u > M - 1) continue;
            d[2 * u] = d[u] + 1;
            if (v[2 * u]) continue;
            q.push(2 * u);
            v[2 * u] = true;
        }
    }
    return d[K];
}

int main() {
    int N, K;
    scanf("%d%d", &N, &K);
    printf("%d", bfs(N, K));
}

思考

关于深度搜索与宽度搜索实际上都有一个比较简单的模板,将模板以及模版题掌握清楚之后完成这类题的难度并不会很大。

DFS

int dfs(int u)
{
    st[u] = true; // st[u] 表示点u已经被遍历过

    for (int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!st[j]) dfs(j);
    }
}

BFS

queue<int> q;
st[1] = true; // 表示1号点已经被遍历过
q.push(1);

while (q.size())
{
    int t = q.front();
    q.pop();

    for (int i = h[t]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!st[j])
        {
            st[j] = true; // 表示点j已经被遍历过
            q.push(j);
        }
    }
}

总结

DFS 和 BFS 主要是运用于对于图和树的搜索,很多问题模型都是可以建模变成一个图或者树的,所以差不多不少问题都会涉及到这两个。比如求二叉树深度,可以是递归的方法,属于 DFS(深度优先搜索);另一种方法是按照层次遍历,属于 BFS(广度优先搜索)。再比如寻找一条路径,利用DFS或BFS寻找从源顶点到终点的路径。

但是不管是BFS还是DFS,它们虽然好用,由于时间和空间的局限性,以至于它们只能解决数据量小的问题。