日韩性视频-久久久蜜桃-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 实现的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 国产美女久久久久 | 日韩欧美成人精品 | 91资源站 | 日韩一级黄色片 | 国产精品18久久久久久vr下载 | 欧美乱做爰xxxⅹ久久久 | 欧美射射| av资源在线播放 | 国产页 | 男同av在线观看一区二区三区 | 天天综合久久综合 | 黄色激情网址 | 欧美日韩爱爱 | 国产乱淫av片杨贵妃 | 成人激情电影在线观看 | 人妻av一区二区三区 | 高潮毛片无遮挡高清免费 | 美日韩一级 | 91禁外国网站 | 男人天堂aaa | 国产免费a级片 | 久久亚洲成人av | 国产无毛av | 亚洲精品乱码久久久久 | 污污免费在线观看 | 国产青草视频在线观看 | caoporn免费在线视频 | 欧美做爰啪啪xxxⅹ性 | www.四虎在线观看 | 麻豆视| 一级片久久久久 | 亚洲精品xxxxx | 美日韩久久| 中文字幕在线观看网 | 国产一区二区视频免费 | www.com操| 日韩高清一级 | 日韩午夜精品视频 | 粗大的内捧猛烈进出视频 | 亚洲色图av在线 | 久久这里 | 搞中出 | 亚洲精品国产无码 | 性生交大片免费看女人按摩 | 黄色一极视频 | 国产精品99一区二区三区 | www.五月婷婷.com | 亚洲色图激情 | 激情春色网 | 中日韩av在线 | 亚洲激情在线观看视频 | 欧洲亚洲一区二区三区 | 久久久久久久久久久国产 | 亚洲一二三视频 | 亚洲自拍色 | 欧美第五页 | 少妇性xxxxxxxxx色武功 | 久久夜夜夜 | 成人免费看毛片 | 久久国产精品精品国产 | 日本不卡高字幕在线2019 | 在线中出| 国产精品毛片视频 | 插骚| 欧美日韩国产电影 | 亚洲精品乱码久久久久久久 | 亚洲区视频在线观看 | 亚洲毛片久久 | www.youjizz.com中国 | 亚洲区小说区图片区qvod | 国产一区二区三区免费视频 | 成人激情综合网 | 日本www视频在线观看 | 欧美一区二区三区成人 | 天天爽网站 | 色99在线| 暧暧视频在线观看 | 奇米久久 | 人妻一区二区三 | 日批视频在线免费看 | 免费中文字幕视频 | 超碰日韩 | 人妻少妇精品中文字幕av蜜桃 | 最近2018年手机中文字幕版 | 肮脏的交易在线观看 | 日韩经典av | 四虎成人精品永久免费av九九 | 午夜精品久久久久久久 | 久久亚洲av永久无码精品 | 五月天狠狠操 | 国产精品高潮av | 久久久久99精品成人片三人毛片 | 国产欧美熟妇另类久久久 | 五月天爱爱 | 日韩伦理一区二区三区 | 青青视频网站 | 操少妇视频| 中文字幕久久久久久久 | 毛片在线看网站 |