題目 : UVa Link
給定一個 M x N 的矩陣 A ,求 A1,1 到 AM,N 的最短路徑長
測資
Input :
2
4
5
0 3 1 2 9
7 3 4 9 9
1 7 5 5 3
2 3 4 2 5
1
6
0 1 2 3 4 5
Output :
24
15
解法
這題要解的就是 Single Source To Other Destinations 的 Shortest Path
我們考慮一下 2 種比較常見的演算法 :
Dijkstra Algorithm | Bellman-Ford Algorithm | |
---|---|---|
策略 | Greedy | Dynamic Program |
可有負邊 | 不可 | 可 |
時間複雜度 | O( N2 ) | O( N3 ) |
由於此題目中邊的權重為 0 ~ 9,沒有負邊
因此選擇使用 Dijkstra Algorithm 更經濟實惠一點
不過在實作演算時我們需要稍微改變一點細節
紀錄與 Source 的最短距離的一為陣列要改為使用二維陣列
此外,我們選擇使用 priority queue 來找出最小邊
除了可以加速演算法,對這題來說也比較好實作
程式碼解說
- dist[m + 2][n + 2] :
紀錄各點到 source (本題是 <1,1> ) 的距離,此外為了讓 index 從 1 開始,在 row 和 column 前面各加了一列(行)空白
此外,為了方便計算,在最後面也各加了一列(行)空白 - checked[m + 2][n + 2] :
紀錄該點使否已經是最短路徑,前後同樣加了空白
並將空白行視為已經是最短路徑,比較方便計算
完整程式碼
1 |
|
複雜度分析
看一下主要的程式碼架構部分
1 | int calculate(const Matrix<int> &m, const int ROW, const int COL) |
維護 priority queue
- min_rec = extract_min(que);
extract a element from priority queue : O(logE) - update_and_relax(m, que, mr, mc);
迴圈次數 2 次 : O(1)
如果有 push element in priority queue : O(logE)
每個頂點都會有 4 條邊 ( 上、下、右、左 )
所以總邊數 = 4 x M x N - M - N –> O(MN) –> O( V )
因此,本題的 Edge 可是大約視作為 Vertex 的數目,所以對 priority queue 的操作也可看為 O( logV )
此外每個邊皆用於 relaxation 一次,priority queue 的操作最多共執行 E 次
所以維護 priority queue 的時間複雜度為 O(VlogV)
迴圈
迴圈最多走訪 V 次
總時間
時間複雜度 : 迴圈 + 維護 priority queue = O(V + VlogV)