弗洛伊德演算法求出最短距離 弗洛伊德演算法

2021-10-11 23:19:36 字數 2770 閱讀 8238

高德地圖相信大家一定都用過,每當我們輸入乙個目的地時,系統總是會幫助我們尋找一條最近的路。我們知道出發地到目的地可能有很多條路可以選擇,而高德地圖是怎樣做到為我們選擇更近的路呢?這一節的內容,我們就會來討論關於圖的最短路徑的問題。

在計算機裡,我們用有權圖來表示城市的路網,其中每個節點代表乙個地點每條邊代表從乙個地方到另乙個地方的距離,資料結構我們使用鄰接矩陣的形式。

計算最短路徑分成兩種情況,一種是一次計算所有點對的最短路徑,就是下面我們要講到的弗洛伊德演算法;另一種是單源最短路徑,也就是計算某乙個節點到其他所有節點的最短距離,後面的迪克斯特拉演算法採用的就是這種方式。

從出發地到目的地的過程中,我們並不是一下子就到達目的地,而是要經過很多的中轉站來幫助我們一步一步地到達目的地。例如下面的圖中,假設 ab,bc 之間的距離分別為 7 和 2。我們看到,a 和 c 之間不能直接通達,因此,要計算 a 和 c 之間的距離,我們就要借助 b 來作為中轉站,因此 a 到 c 的距離為 7 + 2 = 9。

但是,單憑乙個中轉站在有些情況下也是不行的,比如從 d 到 f 就不能只通過乙個中轉站。

因此,計算所有節點之間的最短距離這個大問題可以分為借助

,其中

下面來談一下具體的求解過程,我們首先用鄰接矩陣來表示這張圖,其中

矩陣中每一項的數字代表邊的權重,也就是節點之間的距離。

上面的矩陣也可以代表在不借助中轉站的情況下(

只讓節點a作為中轉站,然後計算各節點的最短路徑,然後對於矩陣的每一項,我們比較d[i][j]d[i][1]+d[1][j]的大小,然後取最小者作為d[i][j]的值。其中ij分別代表矩陣的行和列。

計算後我們發現矩陣中的第 2 行第 5 列從原來的

說明從節點 b 到節點 e 的最短距離在當前狀態下為

。接下來,我們逐漸增加中轉站的個數每增加乙個中轉站的個數,矩陣就更新一次。假設中轉站的個數為

那麼它與上乙個狀態

之間存在這樣的關係

d[i][j] = min(d[i][j], d[i][k] + d[k][j]),於是

遞增到

每遞增一次,矩陣的值就更新一次,最後我們就得到所有點對的最短距離了。

用**表示這個過程非常簡單,只需要幾行就能實現:

def floyd(d):

n = d.shape[0]

for k in range(n):

for i in range(n):

for j in range(n):

d[i][j] = min(d[i][j], d[i][k]+d[k][j])

return d

最後列印出迴圈過後的矩陣。

>>> python floyd.py

>>> [[ 0. 6. 4. 10. 1. 4.]

[ 6. 0. 2. 4. 5. 8.]

[ 4. 2. 0. 6. 3. 6.]

[10. 4. 6. 0. 9. 12.]

[ 1. 5. 3. 9. 0. 3.]

[ 4. 8. 6. 12. 3. 0.]]

例如,第 1 行第 4 列代表從 a 到 d 的最短路徑為 10。

由於程式中存在三重迴圈,所以弗洛伊德演算法的時間複雜度為

而鄰接矩陣有

項,因此空間複雜度自然就為

本節全部**

← 揹包問題(dp)| 演算法與複雜度​zhuanlan.zhihu.com

→ 普林姆演算法 | 演算法與複雜度​zhuanlan.zhihu.com

弗洛伊德演算法

弗洛伊德演算法 floyd 又稱為是插點法。目的是求加權圖中頂點中最短路徑的方法。本文通過舉例子的方法想你具體解釋何為弗洛伊德演算法。有乙個送禮物的問題,是csdn上的乙個題目,題目的詳情是這樣的。hehe和xixi在乙個地方玩遊戲,xixi把n 1件禮物 hehe以前送給xixi的 分別藏在了另外...

弗洛伊德演算法

floyd演算法詳解 求解任意兩點間的最短距離 floyd warshall演算法,簡稱floyd演算法,用於求解任意兩點間的最短距離,時間複雜度為o n 3 我們平時所見的floyd演算法的一般形式如下 1void floyd 注意下第6行這個地方,如果dist i k 或者dist k j 不存...

弗洛伊德演算法

弗洛伊德演算法 求任意一點i到任意一點j的最短路。分析 求i到j的最短路,大可以使用群舉法,因為點都是離散的,i到j的路徑是有限的,所以一定可以通過群舉法得到最短路,但群舉法卻沒太大意義,他的意義在於 把群舉法 通過修改 進行分類,得到好的演算法。flod演算法的分類標準是 通過i到j過點的情況進行...