給定乙個包含非負整數的 m x n 網格,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和為最小。
說明:每次只能向下或者向右移動一步。
示例:
輸入:[
[1,3,1],
[1,5,1],
[4,2,1]
]輸出: 7
解釋: 因為路徑 1→3→1→1→1 的總和最小。
dfs 和 bfs 就好比:你站在乙個多叉口,往前走。 dfs就是沿著一條路一直走,走完了再返回來重新走下一條。 bfs就是你多條路同時進度走,(假如有穿牆的技能)每條路都走一走。(當然,這個例子我覺得和題目比較相關,所以這麼舉例來說明區別,還有乙個是在每個房間找鑰匙的例子來說明區別,詳細的可以參考 《大話資料結構》這本書)
繼續:根據這個例子,可以想到,如果你要驗證從起點能不能到達終點,dfs比較好,也就是圖的連通性。判斷哪條路比較近的話 dfs 和 bfs 理論上的時間複雜度是一樣的,dfs 遞迴寫法簡單一些,但是有可能會爆棧。bfs採用佇列,稍微複雜,比較穩定。碰到具體最短路徑的問題,如果選項只有 bfs 和 dfs 的話,根據實際問題分析,可以兩種演算法思路都考慮一下,如果沒什麼差別的話,我一般選擇bfs,(主要擔心dfs爆棧,需要不斷的剪枝優化)。
// 最小路徑和:矩陣左上角到右下角的最小路徑
// 思路:相當於求兩點之間的最短路徑,所以可以用 bfs
// 使用 visited 二維陣列儲存路徑,借鑑自求遞增路徑的題目
class solution
int minpathsum(vector>& grid)
if ((n = grid[0].size()) == 0)
// 初始化 visited 二維陣列
vector> visited(m, vector(n, int_max));
queuerowqueue;
queuecolqueue;
// 遍歷連通分支(因為矩陣作為圖,肯定連通,所以不用迴圈來遍歷每個連通分支)
// 左上角開始
visited[0][0] = grid[0][0];
rowqueue.push(0);
colqueue.push(0);
int row = 0;
int col = 0;
int r_row = 0;
int r_col = 0;
int d_row = 0;
int d_col = 0;
while (!rowqueue.empty())
// 這裡因為存在int_max 的加法來求路徑和會出現溢位,所以利用減法再加法來避免
visited[r_row][r_col] = min(visited[row][col], visited[r_row][r_col] - grid[r_row][r_col]) + grid[r_row][r_col];
}if (d_row < m && d_col < n)
visited[d_row][d_col] = min(visited[row][col], visited[d_row][d_col] - grid[d_row][d_col]) + grid[d_row][d_col];
}} return visited[m - 1][n - 1];
}};int main()
,, };
cout開頭已經說明,這道題目是動態規劃的題目,所以在這裡附上動態規劃的做法。
思路首先,題目分析可以看出來,從左上角到右下角路徑和,中間節點的路徑和都可以根據前邊已經求出的計算出來。
在乙個矩陣中,因為只能往右和下側走,所以第一行節點的入口只有左側元素,第一列入口只有上乙個元素,所以到這些點的路徑和可以直接求出來。而剩餘節點的路徑和取決於左側和上側,所以在這兩個之間取乙個最小值來與本節點相加得到最小路徑和,依次計算就可以得到最終的結果。時間複雜度為 o(m * n)
**class solution {
public:
int minpathsum(vector>& grid)
{int n=grid.size(),m=grid[0].size();
for(int i=1;i前文說道,圖中最短路徑的方法有很多,還會延伸出其他更多的搜尋演算法 bfs 的擴充套件 a* 以及 dfs 的擴充套件 ida*等等,只怪才疏學淺,不能一一說明,感興趣的可以看一看參考鏈結裡的簡單說明。
這裡要說明一下floyd 和 dijkstra 的區別,floyd 利用的是動態規劃 dp,dijkstra 利用的貪心演算法 greedy,而且dijkstra的演算法中包含與bfs相同的部分,可以理解為在bfs的基礎上加了貪心策略,每次進行最優的判斷。
而 貪心演算法 和 動態規劃演算法區別可以從馬爾可夫模型的角度說起,貪心演算法問題,需要保證每一步都只由之前的乙個狀態得到,這樣才能保證區域性最優是全域性最優。動態規劃可以由之前的多個狀態得到,所以可用貪心演算法解決的問題一定可以用動態規劃解決。(貪心演算法的演算法題再其他部落格說明),這個思考詳細參考部落格: 最後
其實這道題目是很簡單的動態規劃的題目,可以模擬三角形的最小路徑和一塊做,我的博文:三角形最小路徑和
但是我第一時間想到的思路是bfs,雖不是最簡演算法,大概時間複雜度o(2 m*n), 但是正好之前一直在考慮bfs和dfs的區別,還有最短路徑的題目都可以怎麼做,它們具體區別與改進是什麼,本文只是簡單的說明了這道題目怎麼選擇方法,很多擴充套件的演算法的思想以及實踐,還有優劣分析,還有每個演算法常見的應用都沒有提及。本來想全部總結,但是發現越擴充套件越多,失去了這個階段快速練習的意義,但是在這裡立個flag,等找完工作,一定抽空總結。
貪心和動態規劃:
dijkstra 與 bfs:
本應擴充套件的搜路演算法:
dfs,bfs,a* ,ida* :
雙向bfs:
dfs、bfs、dijkstra:
dfs 與 bfs時間複雜度:
如有問題,還望指出
動態規劃之最小編輯距離
1 dp 0 0 表示str1空的子串編輯成str2空的子串的代價為0 2 矩陣dp第一列即dp 0 m 1 0 dp i 0 表示str1 0 i 1 編輯成空串的最小代價,即把str1 0 i 1 中所有字元刪掉的代價,所以dp i 0 dc i 3 矩陣第一行即dp 0 0 n 1 dp 0 ...
演算法題 二 之 最小區間
你有 k 個公升序排列的整數列表。找到乙個最小區間,使得 k 個列表中的每個列表至少有乙個數包含在其中。我們定義如果 b a d c 或者在 b a d c 時 a c,則區間 a,b 比 c,d 小。例如 輸入 4,10,15,24,26 0,9,12,20 5,18,22,30 輸出 20,24...
1631 最小體力消耗路徑(BFS 動態規劃)
1631.最小體力消耗路徑 難度中等127 你準備參加一場遠足活動。給你乙個二維rows x columns的地圖heights,其中heights row col 表示格仔 row,col 的高度。一開始你在最左上角的格仔 0,0 且你希望去最右下角的格仔 rows 1,columns 1 注意下...