1. 程式人生 > >[Qt][Floyd演算法] 動態規劃求解最短行駛路徑 原始碼及演示程式

[Qt][Floyd演算法] 動態規劃求解最短行駛路徑 原始碼及演示程式

首先給出程式下載連結:

[問題描述] 給定一個的矩形網格,設其左上角為起點S。一輛汽車從起點S出發駛向右下角終點T。網格邊上的數字表示距離。在若干網格點處設定了障礙,表示該網格點不可到達。試設計一個演算法,求出汽車從起點S出發到達終點T的一條行駛路程最短的路線。

[結果] 

                    

       說明:滑鼠點選結點可以設定/取消障礙。可在輸入框輸入待查詢的結點(不僅僅侷限於右下角終點)。

[Floyd演算法] 

事實上,Floyd演算法可以求解有向圖的中任意結點間的最短距離,屬於動態規劃的範疇。(不僅侷限於圖中的無向矩陣和首末結點間的最短距離)

       在Floyd演算法中,我們使用的資料結構有:

                int num;              // 結點數目

                 int mat[num][num];       // 鄰接矩陣

                int dist[num][num];   // 輔助矩陣:儲存結點之間的最短路徑長度。

                 int path[num][num];   // 輔助矩陣:用於尋找路徑

  解釋:

        ① 矩陣mat作為鄰接矩陣儲存有向圖。 mat[i][j]表示結點i到結點j的邊權值(mat[i][j] = MAX_INT時,表示兩結點沒有邊)

        ② 矩陣dist

用於儲存任兩結點間的最短路徑長度。dist[i][j]表示從結點i到達結點j的最短距離(dist[i][j] == MAX_INT時,表示i到j不可達)

        ③ 矩陣path中path[i][j]指示從結點i到達結點j的最短路徑要走的下一個結點。

        Floyd演算法的程式碼非常簡短~ 其核心部分可以只用五行程式碼完成,因此先給出演算法的流程,最後再對Floyd演算法作出解釋。

第一步:初始化兩個輔助矩陣:dist[][]和path[][]

for(int i=0; i<num;i++)    /// 初始化 矩陣dist和path
{
   for(int k=0; k<num;k++)
   {
       dist[i][k] = mat[i][k];
       path[i][k] = i;
   }
}
第二步:使用三層for迴圈構造矩陣dist和path
for(int k=0; k<num;k++)   //  對每個結點k,都更新一次所有的dist[i][j]
{
   for(int i = 0; i<num; i++)
   {
      for(int j = 0; j<num; j++)
      {
         if(dist[i][k]+dist[k][j] <dist[i][j]) //對比原來的dist[i][j]和經過k的dist[i][j],取min
         {
            dist[i][j] = dist[i][k]+dist[k][j];
            path[i][j] = path[k][j];
         }
      }
   }
}
// for迴圈結束後,dist和path儲存的便是最短路徑時的結果

由於核心部分只有三層for迴圈,因此Floyd演算法的時間複雜度為O(n^3)

現在再對Floyd演算法作出解釋~

       事實上,Floyd演算法的核心就是這三層for迴圈,其思想是:從任意節點A到任意節點B的最短路徑不外乎2種可能,1是直接從A到B,2是從A經過若干個節點X到B。所以,我們假設dist(AB)為節點A到節點B的最短路徑的距離,對於每一個節點X,我們檢查dist(AX) + dist(XB) < dist(AB)是否成立,如果成立,證明從A到X再到B的路徑比A直接到B的路徑短,我們便設定dist(AB) = dist(AX) + dist(XB),這樣一來,當我們遍歷完所有節點X,dist(AB)中記錄的便是A到B的最短路徑的距離。

      最後利用矩陣path,便可以構造出任意結點間最短路徑的行駛路線~~

相關文章: