一种利用 Dynamic Programming ,求 Graph 中两点之间最短路径的演算法。
考虑 A, B 两点之间的最短路径,若有经过 k 点,则:
A, B 两点之间的最短路径 = A, k 两点之间的最短路径 + k, B 两点之间的最短路径
我们可以将含有 n 个节点的最短路径问题分解成 n 个「是否经过第 k 点」的问题。
以下图为例,计算 节点 0
与 节点 3
之间的最短路径长。由於 节点 0
和 节点 3
作为起点与终点,必然会在路径中被经过,因此我们将「路径只经过 节点 0
和 节点 3
」作为初始状态,再陆续考虑最短路径是否会经过其他节点。
初始状态,最短路径长为 15
:
考虑 节点 1
是否为中继站之一:
节点 0 到节点 1 的最短路径长
+ 节点 1 到 节点 3 的最短路径长
节点 1
影响,而是原先尚未考虑节点 1
时的路径长。9
节点 2
,其路径长为 12
,没有比原先的路径长短,因此最终得到答案为 9
。从上述例子中,可以归纳出下列关系:
假设已经考虑了 k - 1 个节点,现在要考虑第 k 个节点是否为最短路径中的中继站,会有两种可能的最短路径:
A, k 两点之间的最短路径长
+ k, B 两点之间的最短路径长
在两种可能路径中,较短者方为真正的最短路径。
综上所述,可列出以下递回关系式:
考虑 k 个中继节点时, AB 之间的最短路径长 = min(
Ak 两点之间的最短路径长 + kB 两点之间的最短路径长,
考虑 k - 1 个中继节点时, AB 之间的最短路径长
)
# 令 d(A, B, k) 表示 「考虑 k 个中继节点时, AB 之间的最短路径长」
=> d(A, B, k) = min(
d(A, k, k - 1) + d(k, B, k - 1),
d(A, B, k - 1)
)
可以发现,当我们在计算 AB 之间的最短路径
时,会需要考虑 Ak 两点之间的最短路径长
和 kB 两点之间的最短路径长
,纵然在上述例子中可以很容易的算出来,但回顾递回关系式,其中的 d(A, k, k - 1)
+ d(k, B, k - 1)
要每次都计算的话,不仅不好实作,也耗费效能,因此此时正是使用 Dynamic Programming 的时机 (DP:将已经计算好的结果记录下来,下一次使用就可以拿)。
Floyd-Warshall 的实作逻辑
min(原本的成本, 经过第k个点的成本)
以下图为例
接着我们依序计算计算经过 第0点的成本、第1点的成本...第3点的成本
首先是经过第 0 点
接着是经过第 1 点
接着是经过第2点
最後是经过第3点
计算完,这个表格就会是某个点抵达另外一个点最短距离,回到题目,我们要求 0→3 最短距离,可以从表格中得知最短距离为 9
在以下情况不适合使用 Floyd-Warshall 计算最短路径
题目连结:https://leetcode.com/problems/find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance/
题目叙述
测资的 Input/Output
题目的条件
大家好~忧郁的星期一 在前几天我们顺利撷取 Google Analytics 资料到 AWS 中,并...
创建App-现界面与连接 经过了十五天的努力,现在就来看看现有的界面功能吧,我依照功能来区分:登入、...
本节是以 Golang 上游 8854368cb076ea9a2b71c8b3c8f675a8e1...
RealmSwift 昨天分享了 Realm 的基本操作,今天要来分享观察 Realm 资料库的工具...
水底探照灯 教学原文参考:水底探照灯 这篇文章会介绍,如何在 Scratch 3 里使用舞台九倍大角...