【Bellman-Ford算法(求解最短路径约束问题)】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 解释: 城市航班图如下

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

在学习的最短路径算法中,除了迪杰斯特拉算法、弗洛伊德算法之外,还有其他的算法,Bellman-Ford算法就是其中的一种,该算法解决了迪杰斯特拉算法中无法求解负权图的问题,同时对于最短路径中的约束问题也能够求解。

该算法实质上是动态规划算法,具体的算法过程如下:

给定图G(V, E)(其中V、E分别为图G的顶点集与边集),源点s,数组Distant[i]记录从源点s到顶点i的路径长度,初始化数组Distant[n]为无穷大,Distant[s]为0;

以下操作循环执行至多n-1次,n为顶点数: 对于每一条边e(u, v),如果Distant[u] + w(u, v) <Distant[v],则另Distant[v] = Distant[u]+w(u, v)。w(u, v)为边e(u,v)的权值;
若上述操作没有对Distant进行更新,说明最短路径已经查找完毕,或者部分点不可达,跳出循环。否则执行下次循环;

为了检测图中是否存在负环路,即权值之和小于0的环路。对于每一条边e(u, v),如果存在Distant[u] + w(u, v) <Distant[v]的边,则图中存在负环路,即是说改图无法求出单源最短路径。否则数组Distant[n]中记录的就是源点s到各顶点的最短路径长度。

可知,Bellman-Ford算法寻找单源最短路径的时间复杂度为O(V*E).

对于这道题目,我们可以使用该算法的思想:

我们用 f [ t ] [ i ] f[t][i] f[t][i] 表示通过恰好 tt 次航班,从出发城市 s r c src src 到达城市 i i i 需要的最小花费。在进行状态转移时,我们可以枚举最后一次航班的起点 j j j,即:


其中 ( j , i ) ∈ f l i g h t s (j, i)∈flights (j,i)∈flights 表示在给定的航班数组 f l i g h t s flights flights 中存在从城市 j j j 出发到达城市 i i i 的航班, c o s t ( j , i ) cost(j,i) cost(j,i) 表示该航班的花费。该状态转移方程的意义在于,枚举最后一次航班的起点 j j j,那么前 t − 1 t-1 t−1 次航班的最小花费为 f [ t − 1 ] [ j ] f[t−1][j] f[t−1][j] 加上最后一次航班的花费 c o s t ( j , i ) cost(j,i) cost(j,i) 中的最小值,即为 f [ t ] [ i ] f[t][i] f[t][i]。

由于我们最多只能中转 k k k 次,也就是最多搭乘 k + 1 k+1 k+1 次航班,最终的答案即为 f [ 1 ] [ d s t ] , f [ 2 ] [ d s t ] , ⋯ , f [ k + 1 ] [ d s t ] f[1][dst],f[2][dst],⋯,f[k+1][dst] f[1][dst],f[2][dst],⋯,f[k+1][dst]中的最小值。

【代码如下】

class Solution {public:int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {//  f[t][j] 表示经过t个中转(t+1条边)后到达j所需要的最小花费vector<vector<int>> f(k+2,vector<int>(n,10000 * 101 + 1));//  转移方程:f[t][j] = min(f[t-1][i]+cost(i,j)) f[0][src] = 0;for(int t = 1;t<=k+1;t++){for(auto&& flight:flights){int i = flight[0];int j = flight[1];int cost = flight[2];f[t][j] = min(f[t][j],f[t-1][i] + cost);}}//  结果t = 0-k的f[t][j]最小值int ans = 10000 * 101 + 1;for(int t = 0;t<=k+1;t++){ans = min(ans, f[t][dst]);}return ans == 10000 * 101 + 1?-1:ans;}
};

参考文献:
Bellman-Ford算法详解
Bellman-Ford算法
K 站中转内最便宜的航班

【Bellman-Ford算法(求解最短路径约束问题)】787. K 站中转内最便宜的航班——算法分析相关推荐

  1. LeetCode 787. K 站中转内最便宜的航班(图/Bellman Ford算法)

    文章目录 贝尔曼-福特算法(Bellman-Ford) 简介 算法思想 算法执行过程 应用 题目描述 分析 代码 LeetCode 787. K 站中转内最便宜的航班 题目描述 Bellman For ...

  2. 【力扣】787. K 站中转内最便宜的航班加权——有向图最短路径

    前言 我感觉这题比较有代表性,所以记录一下,这题是加权有向图中求最短路径的问题. 题目 787. K 站中转内最便宜的航班 动态规划 假设有一条路径是[src, i, ..., j, dst],解法一 ...

  3. 最短路径-图-----练习力扣787. K 站中转内最便宜的航班

    首先还是搞定三种最短路径的算法. 参考:https://www.cnblogs.com/Halburt/p/10756572.html https://www.cnblogs.com/tahitian ...

  4. 787. K 站中转内最便宜的航班(加权有向图的最短路径)

    题目:787. K 站中转内最便宜的航班 两种方法: 方法一: 思路: 加权图的最短路径 1. 首先将航线转化为字典形式存储.(当前城市–下一城市–费用) 2. 建一个双向队列,元素为元组形式.(当前 ...

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

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

  6. LeetCode——787. K 站中转内最便宜的航班(Cheapest Flights Within K Stops)[中等]——分析及代码(Java)

    LeetCode--787. K 站中转内最便宜的航班[Cheapest Flights Within K Stops][中等]--分析及代码[Java] 一.题目 二.分析及代码 1. 动态规划 ( ...

  7. leetcode每日一题系列——787. K 站中转内最便宜的航班

    787. K 站中转内最便宜的航班 难度中等346收藏分享切换为英文接收动态反馈 有 n 个城市通过一些航班连接.给你一个数组 flights ,其中 flights[i] = [fromi, toi ...

  8. 787. K 站中转内最便宜的航班(动态规划)

    package com.wsq.leetcode; /*** 787. K 站中转内最便宜的航班* @author wsq* @date 2020/10/21有 n 个城市通过 m 个航班连接.每个航 ...

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

    787. K 站中转内最便宜的航班(dp) D A G DAG DAG图直接开二维数组 d p dp dp. 令 d p ( i , j ) dp(i,j) dp(i,j)到达 i i i经过 j j ...

最新文章

  1. 推荐:浏览器是怎样工作的?
  2. 集成学习(ensemble learning)(三)
  3. php中implode()和explode()的应用
  4. index作为key是反模式
  5. java连接到mysql_[操作系统]Java如何连接到MySQL数据库的
  6. 魔兽世界最新网通服务器列表,魔兽世界网通区,魔兽世界网通区在几区
  7. 判定考试成绩程序java_请大家务必按照平时交作业的要求,按时提交!否则会影响您的期末考试成绩。_学小易找答案...
  8. 【转】DICOM 网关的设计与实现
  9. linux按键检测程序,Tiny4412 Linux驱动之按键(使用查询方式) | 技术部落
  10. 遗传算法求解装箱问题c语言,装箱或背包问题? (或者遗传算法解决)
  11. Intel CPU命名规则
  12. java byte与char互转原理
  13. 读书笔记_Effective_C++_条款二:尽量以const, enum, inline替换#define
  14. 架构师补给站之EA(企业架构)
  15. 9款优秀的代码比对工具,没用过就很离谱
  16. 一个都不能少:全面认识IE插件
  17. steam怎么设公用计算机,steam怎样设置家庭共享 steam家庭共享设置办法
  18. Android8怎么格式化内存卡,安卓手机怎么格式化存储内存 Android手机SD内存卡格式化方法...
  19. 郑职院官计算机网络,2020年陕西省青年职业技能大赛计算机网络管理员决赛开幕式在汉中职院举行...
  20. python-flask 设置网页保留缓存静态文件时间

热门文章

  1. 电子与通信的专业复试QA
  2. 谷歌招聘新员工五大标准:文凭一边玩去
  3. 万万没想到,年终奖这样计税,竟是喜上添喜!
  4. openGL推荐学习资料
  5. 王幼军:拉普拉斯概率理论的历史研究
  6. Python数据可视化_简单绘图_汇总(一)
  7. 探花交友_第1章_项目介绍以及实现登录功能_第2节_项目介绍
  8. 裁剪特定时长音乐需求之Audacity
  9. 西北工业大学计算机学硕复试,分享:西北工业大学计算机考研复试经验_跨考网...
  10. 雅思作文 顾家北雅思作文 学习记录