[M最短路] lc787. K 站中转内最便宜的航班(Bellman-Ford算法模板+边数限制最短路+dp思想)

Posted Ypuyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[M最短路] lc787. K 站中转内最便宜的航班(Bellman-Ford算法模板+边数限制最短路+dp思想)相关的知识,希望对你有一定的参考价值。

1. 题目来源

链接:787. K 站中转内最便宜的航班

模板:[图+最短路+模板] 五大最短路常用模板

2. 题目解析

很明显的一道 Bellman-Ford 算法的模板题,边数限制最短路。其中 Bellman-Fordspfa 的前身,两者属于同一个思想,且同 Floyd 都是用的 dp 的思想。而 dijkstra 算法采用的是贪心的思想。

dp 思想:

  • 状态定义:f[k][i] 表示从起点 src 最多经过 k 条边的所有路径中,到达 i 点的最短距离。
  • 状态转移:f[k][i] = min(f[k-1][i], f[k-1][j] + w[j][i])即需要枚举 i 的所有入边,枚举每个点进行状态转移,等价于要枚举每个点的所有入边,即枚举所有边。
  • 空间优化:很明显,f[k] 仅与 f[k-1] 有关,故可以使用滚动数组,记录上一次的状态,并在状态转移的时候实用上一次的状态进行更新即可。即可将空间变为 1 维。

  • 时间复杂度 O ( n k ) O(nk) O(nk)
  • 空间复杂度 O ( n ) O(n) O(n)

代码:

const int N = 105;
int dist[N], backup[N];

class Solution {
public:
    int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
        memset(dist, 0x3f, sizeof dist);
        dist[src] = 0;
        for (int i = 0; i < k + 1; i ++ ) {                 // 枚举 k+1 条边的限制
            memcpy(backup, dist, sizeof dist);              // 滚动数组,backup-->f[k-1],dist-->f[k]
            for (int j = 0; j < flights.size(); j ++ ) {    // 枚举所有边
                int a = flights[j][0], b = flights[j][1], c = flights[j][2];
                dist[b] = min(dist[b], backup[a] + c);
            }
        }
        if (dist[dst] == 0x3f3f3f3f) return -1;

        return dist[dst];
    }
};

简洁代码:

class Solution {
public:
    const int INF = 1e8;

    int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {
        vector<int> dist(n, INF);
        dist[src] = 0;
        K ++ ;
        while (K -- ) {
            auto cur = dist;
            for (auto& e: flights) {
                int a = e[0], b = e[1], c = e[2];
                cur[b] = min(cur[b], dist[a] + c);
            }
            dist = cur;
        }
        if (dist[dst] == INF) return -1;
        return dist[dst];
    }
};

以上是关于[M最短路] lc787. K 站中转内最便宜的航班(Bellman-Ford算法模板+边数限制最短路+dp思想)的主要内容,如果未能解决你的问题,请参考以下文章

[leetcode] 787 K 站中转内最便宜的航班

leetcode_787K 站中转内最便宜的航班

787. K 站中转内最便宜的航班(dp)

LeetCode 789. 逃脱阻碍者(贪心) / 1646. 获取生成数组中的最大值 / 787. K 站中转内最便宜的航班(有限制的最短路,重新审视迪杰斯特拉,动态规划)

缺迪杰斯特拉和SPFA] 文巾解题 787. K 站中转内最便宜的航班

LeetCode 787 K站中转内最便宜的航班[动态规划] HERODING的LeetCode之路