Floyd演算法與動態規劃
PS:本文是在他人博文基礎上加以修改而來,將從 Ak(i,j) 推導 Ak-1(i,j) 改為從 Ak-1(i,j) 推導 Ak(i,j),為的是符合自己的思維習慣,更好的理解floyd算法,並且方便以後檢視。
在此首先對原作者表示感謝!
下面進入正文
floyd的程式碼實現其實很簡單:
-
void floyd() -
{ -
for(k=0;k<n;k++) -
for(i=0;i<n;i++) -
for(j=0;j<n;j++) -
A[i][j]=min(A[i][j],A[i][k]+A[k][j]); -
}
floyd演算法是一個經典的動態規劃演算法,目標是尋找從點i到點j(圖中任意兩點)的最短路徑。從動態規劃的角度看問題,我們需要為這個目標重新做一個詮釋(這個詮釋正是動態規劃最富創造力的精華所在)。假設圖有n個頂點,依次為0,1,…,n-1,floyd演算法加入了這個概念
Ak(i,j):表示從頂點i到頂點j且中間頂點的序號不大於K的最短路徑。
這個限制的重要之處在於,它將最短路徑的概念做了限制,使得該限制有機會滿足迭代關係,這個迭代關係就在於研究:假設Ak-1(i,j)已知,是否可以藉此推匯出Ak(i,j)。針對此問題,採用數學歸納法,我們分兩步解決:
1、由Ak(i,j)的定義可得初始狀態(即中間不經過其他任何頂點):A-1(i,j) = cost(i,j)。(cost(i,j)為連線頂點i 和頂點j 的邊的權值,若兩頂點間無邊,則值為無窮大)
2、假設此時Ak-1(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呢?因為Ak-1是我們目前得到的最優解。那麼遇到第二種情況,Ak(i,j)不經過點k時,由於沒有經過點k,所以根據概念,可以得出Ak
Ak(i,j) = min( Ak-1(i,j), Ak-1(i,k) + Ak-1(k,j) )
到這裡,已經列出了求取Ak(i,j)的整個演算法了,但是,最終的目標是求dist(i,j),即i到j的最短路徑,如何把Ak(i,j)轉換為dist(i,j)?這個其實很簡單,當k=n-1(n表示圖中頂點的個數)的時候,即是說,An-1(i,j)=dist(i,j)。那是因為當k已經最大時,已經不存在索引比k大的點了,那這時候的An-1(i,j)其實就已經是頂點i 到頂點j 的最短路徑了。
從動態規劃演算法設計的角度來講,求解決策過程的最優化問題,首先應將待求解問題分解成若干個子問題,確定待求解問題與子問題的定量關係,先求解子問題,然後從這些子問題的解得到原問題的解。而本文可看做求解定量關係部分(即由子問題出發,求解原問題)。
個人總結:劃分的過程是從上往下,求解的過程是從下往上。