首先給出程序下載鏈接:
源碼及可執行程序的下載鏈接:http://download.csdn.net/detail/mahabharata_/9757206
[問題描述] 給定一個的矩形網格,設其左上角爲起點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和pathfor(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,便可以構造出任意結點間最短路徑的行駛路線~~
相關文章:
[1] 博客 - floyd算法:http://blog.csdn.net/zhongkeli/article/details/8832946
[2] 博客 - floyd算法詳講:http://blog.csdn.net/niushuai666/article/details/6772706