日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

棋盘最短路径 python_Dijkstra 最短路径算法 Python 实现

發布時間:2025/4/5 python 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 棋盘最短路径 python_Dijkstra 最短路径算法 Python 实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Dijkstra 最短路徑算法 Python 實現

問題描述

使用 Dijkstra 算法求圖中的任意頂點到其它頂點的最短路徑(求出需要經過那些點以及最短距離)。

以下圖為例:

算法思想

可以使用二維數組來存儲頂點之間邊的關系

首先需要用一個一維數組 dis 來存儲 初始頂點到其余各個頂點的初始路程,以求 1 頂點到其它各個頂點為例:

將此時 dis 數組中的值稱為最短路的“估計值”。

既然是求 1 號頂點到其余各個頂點的最短路程,那就先找一個離 1 號頂點最近的頂點。通過數組 dis 可知當前離 1 號頂點最近是 2 號頂點。當選擇了 2 號頂點后,dis[2] 的值就已經從“估計值”變為了“確定值”,即 1 號頂點到 2 號頂點的最短路程就是當前 dis[2]值。為什么呢?因為目前離 1 號頂點最近的是 2 號頂點,并且這個圖所有的邊都是正數,那么肯定不可能通過第三個頂點中轉,使得 1 號頂點到 2 號頂點的路程進一步縮短了。

既然選了 2 號頂點,接下來再來看 2 號頂點有哪些出邊。有 2->3 和 2->4 這兩條邊。先討論通過 2->3 這條邊能否讓 1 號頂點到 3 號頂點的路程變短。也就是說現在比較 dis[3] 和 dis[2] + G[2][3]的大小。其中 dis[3] 表示 1 號頂點到 3 號頂點的路程。dis[2] + G[2][3] 中 dis[2] 表示 1 號頂點到 2 號頂點的路程,G[2][3] 表示 2->3 這條邊。所以 dis[2] + G[2][3] 就表示從 1 號頂點先到 2 號頂點,再通過 2->3 這條邊,到達 3 號頂點的路程。

在本例中 dis[3] = 12,dis[2] + G[2][3] = 1 + 9 = 10,dis[3] > dis[2] + G[2][3],所以 dis[3] 要更新為 10。這個過程有個專業術語叫做“松弛”。即 1 號頂點到 3 號頂點的路程即 dis[3],通過 2->3 這條邊松弛成功。這是 Dijkstra 算法的主要思想:通過“邊”來松弛初始頂點到其余各個頂點的路程。

同理通過 2->4(G[2][4]),可以將 dis[4]的值從 ∞ 松弛為 4(dis[4] 初始為 ∞,dis[2] + G[2][4] = 1 + 3 = 4,dis[4] > dis[2] + G[2][4],所以 dis[4] 要更新為 4)。

剛才對 2 號頂點所有的出邊進行了松弛。松弛完畢之后 dis 數組為:

接下來,繼續在剩下的 3、4、5 和 6 號頂點中,選出離 1 號頂點最近的頂點。通過上面更新過 dis 數組,當前離 1 號頂點最近是 4 號頂點。此時,dis[4] 的值已經從“估計值”變為了“確定值”。下面繼續對 4 號頂點的所有出邊(4->3,4->5 和 4->6)用剛才的方法進行松弛。松弛完畢之后 dis 數組為:

繼續在剩下的 3、5 和 6 號頂點中,選出離 1 號頂點最近的頂點,這次選擇 3 號頂點。此時,dis[3] 的值已經從“估計值”變為了“確定值”。對 3 號頂點的所有出邊(3->5)進行松弛。松弛完畢之后 dis 數組為:

繼續在剩下的 5 和 6 號頂點中,選出離 1 號頂點最近的頂點,這次選擇 5 號頂點。此時,dis[5] 的值已經從“估計值”變為了“確定值”。對5號頂點的所有出邊(5->4)進行松弛。松弛完畢之后 dis 數組為:

最后對 6 號頂點所有點出邊進行松弛。因為這個例子中 6 號頂點沒有出邊,因此不用處理。到此,dis 數組中所有的值都已經從“估計值”變為了“確定值”。

最終 dis 數組如下,這便是 1 號頂點到其余各個頂點的最短路徑。

總結一下剛才的算法。算法的基本思想是:每次找到離源點(上面例子的源點就是 1 號頂點)最近的一個頂點,然后以該頂點為中心進行擴展,最終得到源點到其余所有點的最短路徑。基本步驟如下:將所有的頂點分為兩部分:已知最短路程的頂點集合 P 和未知最短路徑的頂點集合 Q。最開始,已知最短路徑的頂點集合 P 中只有源點一個頂點。這里用一個 visited[ i ]數組來記錄哪些點在集合 P 中。例如對于某個頂點 i,如果 visited[ i ]為 1 則表示這個頂點在集合 P 中,如果 visited[ i ]為 0 則表示這個頂點在集合 Q 中;

設置源點 s 到自己的最短路徑為 0 即 dis = 0。若存在源點有能直接到達的頂點 i,則把 dis[ i ]設為 G[s][ i ]。同時把所有其它(源點不能直接到達的)頂點的最短路徑為設為 ∞;

在集合 Q 的所有頂點中選擇一個離源點 s 最近的頂點 u(即 dis[u] 最小)加入到集合 P。并考察所有以點 u 為起點的邊,對每一條邊進行松弛操作。例如存在一條從 u 到 v 的邊,那么可以通過將邊 u->v 添加到尾部來拓展一條從 s 到 v 的路徑,這條路徑的長度是 dis[u] + G[u][v]。如果這個值比目前已知的 dis[v] 的值要小,我們可以用新值來替代當前 dis[v] 中的值;

重復第 3 步,如果集合 Q 為空,算法結束。最終 dis 數組中的值就是源點到所有頂點的最短路徑

Dijkstra 算法不能應用于有負權重的圖

Dijkstra 時間復雜度為 O(N2)

Python 實現1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50def (G, start):

start = start - 1

inf = float('inf')

node_num = len(G)

visited = [0] * node_num

dis = {node: G[start][node] for node in range(node_num)}

parents = {node: -1 for node in range(node_num)}

# 起始點加入進 visited 數組

visited[start] = 1

# 最開始的上一個頂點為初始頂點

last_point = start

for i in range(node_num - 1):

# 求出 dis 中未加入 visited 數組的最短距離和頂點

min_dis = inf

for j in range(node_num):

if visited[j] == 0 and dis[j] < min_dis:

min_dis = dis[j]

# 把該頂點做為下次遍歷的上一個頂點

last_point = j

# 最短頂點假加入 visited 數組

visited[last_point] = 1

# 對首次循環做特殊處理,不然在首次循環時會沒法求出該點的上一個頂點

if i == 0:

parents[last_point] = start + 1

for k in range(node_num):

if G[last_point][k] < inf and dis[k] > dis[last_point] + G[last_point][k]:

# 如果有更短的路徑,更新 dis 和 記錄 parents

dis[k] = dis[last_point] + G[last_point][k]

parents[k] = last_point + 1

# 因為從 0 開始,最后把頂點都加 1

return {key + 1: values for key, values in dis.items()}, {key + 1: values for key, values in parents.items()}

if __name__ == '__main__':

inf = float('inf')

G = [[0, 1, 12, inf, inf, inf],

[inf, 0, 9, 3, inf, inf],

[inf, inf, 0, inf, 5, inf],

[inf, inf, 4, 0, 13, 15],

[inf, inf, inf, inf, 0, 4],

[inf, inf, inf, inf, inf, 0]]

dis, parents = Dijkstra(G, 1)

print("dis: ", dis)

print("parents: ", parents)

輸出為1

2dis: {1: 0, 2: 1, 3: 8, 4: 4, 5: 13, 6: 17}

parents: {1: -1, 2: 1, 3: 4, 4: 2, 5: 3, 6: 5}

如果求 1 號頂點到 6 號頂點的最短距離,dis[6] = 17,所以最短距離為 17。

再看 parents[6] = 5,說明 6 號頂點的上一個頂點為 5,parents[5] = 3,說明 5 號頂點的上一個頂點為 3,以此類推,最終 1 號頂點到 6 號頂點的路徑為 1->2->4->3->5->6。

優化思路其中每次找到離 1 號頂點最近的頂點的時間復雜度是 O(N),可以用“堆”來優化,使得這一部分的時間復雜度降低到 O(logN);

另外對于邊數 M 少于 N2 的稀疏圖來說(把 M 遠小于 N2 的圖稱為稀疏圖,而 M 相對較大的圖稱為稠密圖),可以用鄰接表來代替鄰接矩陣,使得整個時間復雜度優化到 O((M+N)logN)。注意,在最壞的情況下 M 就是 N2,這樣的話 MlogN 要比 N2 還要大。但是大多數情況下并不會有那么多邊,所以 (M+N)logN 要比 N2 小很多

總結

以上是生活随笔為你收集整理的棋盘最短路径 python_Dijkstra 最短路径算法 Python 实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩精品啪啪 | 天天色棕合合合合合合合 | av色图片 | 精品久久人妻av中文字幕 | 91色伦| 穿扒开跪着折磨屁股视频 | 亚洲精品a区 | 欧亚一区二区三区 | 大奶一区二区 | 国产欧美二区 | 91蜜桃传媒精品久久久一区二区 | av在线二区| 日本裸体网站 | 国内精品久久久 | 久久黄页 | 一级女人毛片 | 国产第六页 | 国产精品视频第一页 | 久久综合色综合 | 国产视频精品一区二区三区 | 天天操天天操天天 | 亚洲精品视频免费 | 中出白浆 | 日韩一区二区影视 | 国产免费一区二区三区免费视频 | 久久久男人的天堂 | 在线观看中文字幕亚洲 | youjizz国产精品 | 色八戒av | 激情五月深爱五月 | 波多野结衣一区二区三区在线 | 欧美丰满熟妇xxxx | 老熟女毛茸茸浓毛 | 亚洲乱妇 | 超碰人人人人 | 国产一区二区三区四 | 国产农村妇女毛片精品久久麻豆 | 国产视频网站在线观看 | 欧美激情视频在线观看 | 先锋资源一区 | 日韩精品视频在线免费观看 | 日本中文在线观看 | 亚洲人女屁股眼交6 | 欧美sm凌虐视频网站 | 成av人片一区二区三区久久 | 一级在线看 | 国产精品嫩草影院桃色 | 亚洲国产精品99久久久久久久久 | 国产网站黄| 97av在线视频| 无码人妻aⅴ一区二区三区69岛 | 中文乱码人妻一区二区三区视频 | 国产一级大片在线观看 | 成人久久视频 | 国产欧美日韩精品一区二区三区 | 99久久视频 | 懂色av一区二区三区免费 | 美女超碰 | 国产亚洲二区 | 日本亚洲在线 | 女人久久| 日韩精品少妇 | 深夜视频在线看 | 亚洲一二区视频 | 亚洲欧美日韩不卡 | 国产欧美网站 | 色视频免费| 欧美日韩精品在线视频 | 欧美精品成人 | 小日子的在线观看免费第8集 | 午夜国产免费 | 97人人爱 | 狠狠操中文字幕 | 久久久国产精品成人免费 | 老司机av福利 | 美色视频| 日日躁夜夜躁aaaabbbb | 1024国产在线 | 久久久剧场 | 亚洲欧美另类日韩 | 福利影院在线观看 | 人妻少妇一区二区三区 | 极品videosvideo喷水 | 日韩欧美精品久久 | av永久免费在线观看 | 国产精品区一区二区三 | av不卡中文字幕 | 午夜激情网 | 亚洲av无码成人精品区 | 日韩三级视频在线播放 | 欧美变态视频 | 精品国产二区三区 | 成人激情文学 | 亚洲国产福利 | 成人看片在线观看 | 亚洲干综合 | 97精品人妻一区二区三区蜜桃 | 九色视频偷拍少妇的秘密 | 久久综合婷婷国产二区高清 |