floyd演算法是乙個經典的動態規劃演算法。用通俗的語言來描述的話,首先我們的目標是尋找從點i到點j的最短路徑。從動態規劃的角度看問題,我們需要為這個目標重新做乙個詮釋(這個詮釋正是動態規劃最富創造力的精華所在),floyd演算法加入了這個概念
ak(i,j):表示從i到j中途不經過索引比k大的點的最短路徑。
這個限制的重要之處在於,它將最短路徑的概念做了限制,使得該限制有機會滿足迭代關係,這個迭代關係就在於研究:假設ak(i,j)已知,是否可以藉此推導出ak-1(i,j)。
假設我現在要得到ak(i,j),而此時ak(i,j)已知,那麼我可以分兩種情況來看待問題:1. ak(i,j)沿途經過點k;2. ak(i,j)不經過點k。如果經過點k,那麼很顯然,ak(i,j) = ak-1(i,k) + ak-1(k,j),為什麼是ak-1呢?因為對(i,k)和(k,j),由於k本身就是源點(或者說終點),加上我們求的是ak(i,j),所以滿足不經過比k大的點的條件限制,且已經不會經過點k,故得出了ak-1這個值。那麼遇到第二種情況,ak(i,j)不經過點k時,由於沒有經過點k,所以根據概念,可以得出ak(i,j)=ak-1(i,j)。現在,我們確信有且只有這兩種情況---不是經過點k,就是不經過點k,沒有第三種情況了,條件很完整,那麼是選擇哪乙個呢?很簡單,求的是最短路徑,當然是哪個最短,求取哪個,故得出式子:
ak(i,j) = min( ak-1(i,j), ak-1(i,k) + ak-1(k,j) )
因此floyd的最外層迴圈:
for (k = 0; k < n; k++) ...
就是分別求出 a0(i,j), a1(i,j), ..., an(i,j)
演算法描述:
(1) 用陣列dis[i][j]來記錄i,j之間的最短距離。初始化dis[i][j],
若i=j則dis[i][j]=0,
若i,j之間有邊連線則dis[i][j]的值為該邊的權值,否則dis[i][j]的值為 。
(2) 對所有的k值從1到n,修正任意兩點之間的最短距離,計算dis[i][k]+dis[k][j]的值,若小於dis[i][j],則dis[i][j]= dis[i][k]+dis[k][j],否則dis[i][j]的值不變
程式:
1void floyd(int dis[n + 1][n + 1], int path[n + 1][n + 1], intn)2
11}12}
13}14 }
正確性證明(歸納法) :
對於任意兩點a,b:
(1)當從a到b之間的最短路徑,在中間沒有經過頂點或經過1個頂點號為1的頂點時,演算法顯然正確。
(2)假設a到b經過的最大頂點號不超過k-1時,演算法得到的最短距離是正確的
(3)當a到b經過的最大頂點號為k時,則從a到頂點號為k的頂點v 之間的頂點號均不大於k-1,從v 到b之間的頂點號也不大於k-1,由假設2得,
a到vk的距離是中間頂點號不超過k-1的最短距離,vk到b的距離是中間頂點號不超過k-1的最短距離,所以a經vk到b為a,b之間經過最大號
為k的路徑中距離最短的,由演算法修正a,b的最短距離,即可得到a,b間頂點號不超過k的最短距離。
(4)綜上所述,演算法是正確的
時間複雜度:o(n3)
Floyd演算法思想
本來 量如此小的演算法不用出模板了,但是的確思想還是很好的。1.定義概覽 floyd warshall演算法 floyd warshall algorithm 是解決任意兩點間的最短路徑的一種演算法,可以正確處理有向圖或負權的最短路徑問題,同時也被用於計算有向圖的傳遞閉包。floyd warshal...
Floyd演算法簡介
演算法定義 floyd warshall演算法 floyd warshall algorithm 是解決任意兩點間的最短路徑的一種演算法,可以正確處理有向圖或負權的最短路徑問題,同時也被用於計算有向圖的傳遞閉包。floyd warshall演算法的時間複雜度為o n 3 空間複雜度為o n2 演算法...
Floyd演算法 模板
floyd演算法又稱為插點法,是一種用於尋找給定的加權圖中多源點之間最短路徑的演算法。該演算法名稱以創始人之一 1978年圖靈獎獲得者 史丹福大學電腦科學系教授羅伯特 弗洛伊德命名。注意 其實很多題目不是直接問你 floyd 怎麼求最短路徑,而是要你利用 floyd 的動態規劃思想解決類似 floy...