這裡我一直好奇的是這三個漂亮的迴圈是怎麼完成最終正確的結果的,如何證明它們是正確的。直到看了這裡的解析,才算弄懂了。
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) )
現在已經得出了ak(i,j) = ak-1(i,k) + ak-1(k,j)這個遞迴式,但顯然該遞迴還沒有乙個出口,也就是說,必須定義乙個初始狀態,事實上,這個初始狀態取決於索引k是從0開始還是從1開始,上面的**是c寫的,是以0為開始索引,但一般描述演算法似乎習慣用1做開始索引,如果是以1為開始索引,那麼初始狀態值應設定為a0了,a0(i,j)的含義不難理解,即從i到j的邊的距離。也就是說,a0(i,j) = cost(i,j) 。由於存在i到j不存在邊的情況,也就是說,在這種情況下,cost(i,j)無限大,故a0(i,j) = oo(當i到j無邊時)
到這裡,已經列出了求取ak(i,j)的整個演算法了,但是,最終的目標是求dist(i,j),即i到j的最短路徑,如何把ak(i,j)轉換為dist(i,j)?這個其實很簡單,當k=n(n表示索引的個數)的時候,即是說,an(i,j)=dist(i,j)。那是因為當k已經最大時,已經不存在索引比k大的點了,那這時候的an(i,j)其實就已經是i到j的最短路徑了。
從floyd演算法中不難看出,要設計乙個好的動態規劃演算法,首先需要研究是否能把目標進行重新詮釋(這一步是最關鍵最富創造力的一步),轉化為乙個可以被分解的子目標,如果可以轉化,就要想辦法尋找數學等式使目標收斂為子目標,如果這一步可以實現了,還需要研究該遞迴收斂式的出口,即初始狀態是否明確(這一步往往已經簡單了)。
Floyd 動態規劃的理解
這裡我一直好奇的是這三個漂亮的迴圈是怎麼完成最終正確的結果的,如何證明它們是正確的。直到看了這裡的解析,才算弄懂了。floyd演算法是乙個經典的動態規劃演算法。用通俗的語言來描述的話,首先我們的目標是尋找從點i到點j的最短路徑。從動態規劃的角度看問題,我們需要為這個目標重新做乙個詮釋 這個詮釋正是動...
floyd演算法和動態規劃
long long ago就已經知道了floyd演算法,關鍵 就4行,也容易記住,上上週又看到了floyd,都說是動態規劃,所以特意去學了一圈動態規劃,今天終於又回到了它 d k i j 定義 只能使用第1號到第k號點作為中間媒介時,點i到點j之間的最短路徑長度。在動態規劃演算法中,處於首要位置 且...
探求Floyd演算法的動態規劃本質
floyd warshall 簡稱floyd演算法 是一種著名的解決任意兩點間的最短路徑 all paris shortest paths,apsp 的演算法。從表面上粗看,floyd演算法是乙個非常簡單的三重迴圈,而且純粹的floyd演算法的迴圈體內的語句也十分簡潔。我認為,正是由於 floyd演...