LC-787. K 站中转内最便宜的航班

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

有 n 个城市通过一些航班连接。给你一个数组 flights ,其中 flights[i] = [fromi, toi, pricei] ,表示该航班都从城市 fromi 开始,以价格 pricei 抵达 toi。

现在给定所有的城市和航班,以及出发城市 src 和目的地 dst,你的任务是找到出一条最多经过 k 站中转的路线,使得从 src 到 dst 的 价格最便宜 ,并返回该价格。 如果不存在这样的路线,则输出 -1。

示例 1:

输入:
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
src = 0, dst = 2, k = 1
输出: 200
解释:
城市航班图如下
LC-787. K 站中转内最便宜的航班

从城市 0 到城市 2 在 1 站中转以内的最便宜价格是 200,如图中红色所示。
解析:

这是一道最短路径问题,可是有一个步数k的限定,dijkstra无法限定步数,spfa也不可以,那就要考虑spfa的原生算法,Bellman Ford

Bellman Ford/SPFA 都是基于动态规划,其原始的状态定义为 f[i][k],f[i][k] 代表从起点到 i 点,且经过最多 k 条边的最短路径。这样的状态定义引导我们能够使用 Bellman Ford 来解决有边数限制的最短路问题。
同样多源汇最短路算法 Floyd 也是基于动态规划,其原始的三维状态定义为 f[i][j][k],f[i][j][k] 代表从点 i 到点 j,且经过的所有点编号不会超过 k(即可使用点编号范围为 [1, k])的最短路径。这样的状态定义引导我们能够使用 Floyd 求最小环或者求“重心点”(即删除该点后,最短路值会变大

class Solution {
public:
    int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
        //dp[i][j] 表示走了i步,到达j点花费最小
        vector<vector<int>> dp(k + 2, vector<int>(n + 1, INT_MAX / 2));
        dp[0][src] = 0;
        for(int i = 1; i <= k + 1; i++) {
            for(auto &k : flights) {
                int x = k[0], y = k[1], z = k[2];
                dp[i][y] = min(dp[i - 1][x] + z, dp[i][y]);
            }
        }
        int ans = INT_MAX / 2;
        for(int i = 0; i <= k + 1; i++) {
            ans = min(ans, dp[i][dst]);
        }
        return ans == INT_MAX / 2 ? -1 :ans;
    }
};
上一篇:b_lc_ 最小化目标值与所选元素的差(dp / bitset 优化内存)


下一篇:在Mac下远程登录Linux时,提示cannot change locale (UTF-8) No such file or directory