最短路径算法----Floyd-warshall(十字交叉算法证明)
Floyd不同于Dijkstra,可以得到所有點對的最短路徑。使用的是DP
Floyd可以處理有負權重邊的情況
遞推公式:w(i, j) = min{w(i, j), w(i, k) + w(k, j)},含義是【i到j的最短距離】=【i到k的最短距離+k到j的最短距離】與【i到j的最短距離】中較小的那一個
看起來很簡單,但是具體怎么計算呢?
依舊使用這個例子,圖的表示方式為:
[[0, 7, 9, max, max, 14],[7, 0, 10, 15, max, max],[9, 10, 0, 11, max, 2],[max, 15, 11, 0, 6, max],[max, max, max, 6, 0, 9],[14,max, 2, max, 9, 0]] 可以看出,w(i, i) = 0。這就是突破口了。
當k=0時,w(0, j)=min{w(0,0)+w(0,j), w(0,j)};w(i,0)=min{w(i,0)+w(0,0), w(i,0)},是不用更新的。當然,k不為0的時候,需要更新w(0,j)和w(i,0)
類似的,可以得到w(k,j)和w(i,k)不用更新。也就是說,和k相同行、列不用更新。
用圖做個例子:求圖中藍色的值w(4,2)
w(4,2) = min{w(4,2) + 紅色兩個格子的和+綠色兩個格子的和+紫色兩個格子的和+薄荷色兩個格子的和}
1. 可以看出k=2和k=4的時候,更新時沒有意義的。
2. 可以看出,計算過程其實就是畫一個(k,k)-(4,2)的方框,比較w(4,2)和方框的另外兩個頂點w(4,k)+w(k,2)的大小。當然,這個時候w(4,k)和w(k,2)應該也是最優的解。
所以明顯不能以i,j,k的loop順序遍歷。
那么試一下以k,i,j的loop順序遍歷呢?
這里有個很取巧的點:
1. 當k=0的時候,第一行、第一列已經是k=0的最優解了(還記得前面的結論嗎)
2. 當k=0的時候,其他的行、列只用取第一行、第一列的數據
也就是說,當k=0的時候,遍歷完整張圖,能得到k=0的情況下dp算法的最優解:當且僅當中間節點編號<=0的時候,點i到點j的最近值
繼續證明k=x的情況下最優解已經得到,k=x+1時繼續遍歷,能否得到k=x+1的最優解?
1. k=x+1的時候,第x+1行、第x+1列已經是k<=x+1的最優解了(k=x+1時,不用更新第x行、第x列)
2. k=x+1的時候,其他的行、列只會讀取第x+1行、第x+1列的數據
因此當k=x+1時,遍歷完整張圖,能得到k=x+1的情況下dp算法的最優解。
證明完畢
以上的證明過程也就是“十字交叉算法”的原理了。
感興趣的同學可以網上搜一下,瞬間即懂
def floyd(graph):# graph:n*n matrix# find min distance from start_node to end_nodelength = len(graph)for k in xrange(0, length):for i in xrange(0, length):for j in xrange(0, length):graph[i][j] = min(graph[i][k] + graph[k][j], graph[i][j])return graph
時間復雜度O(n^3)
驅動
graph = [[0, 7, 9, max_int, max_int, 14],[7, 0, 10, 15, max_int, max_int],[9, 10, 0, 11, max_int, 2],[max_int, 15, 11, 0, 6, max_int],[max_int, max_int, max_int, 6, 0, 9],[14, max_int, 2, max_int, 9, 0]] print floyd(graph)
附錄:
打印出最短路徑
def floyd(graph):# graph:n*n matrix# find min distance from start_node to end_nodelength = len(graph)pre_node = [[-1 for i in xrange(0, length)] for j in xrange(0, length)]for k in xrange(0, length):for i in xrange(0, length):for j in xrange(0, length):dist = graph[i][k] + graph[k][j]if dist < graph[i][j]:graph[i][j] = distpre_node[i][j] = kprint "pre_node", pre_nodereturn graph
總結
以上是生活随笔為你收集整理的最短路径算法----Floyd-warshall(十字交叉算法证明)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Scapy:send函数剖析(参数、返回
- 下一篇: URLOS安装、升级、卸载