動態規劃3:矩陣最小路徑和問題
題目:有一個矩陣map,它每個格子有一個權值。從左上角的格子開始每次只能向右或者向下走,最後到達右下角的位置,路徑上所有的數字累加起來就是路徑和,返回所有的路徑中最小的路徑和。
給定一個矩陣map及它的行數n和列數m,請返回最小路徑和。保證行列數均小於等於100.
測試樣例:[[1,2,3],[1,1,1]],2,3返回:4
思路:單純從問題來看,這是一個非常複雜的問題,需要大量的遍歷操作。分析得知:每一個位置map[i][j]只可能來自map[i][j-1]向右走一個結點或者map[i-1][j]向下走一個結點,因此只需要比較到達map[i][j-1]和到達map[i-1][j]的路徑較小值加上map[i][j]就是所求答案,這時考慮使用遞迴,但是可知,這種遞迴處理屬於暴力搜尋的方式,因為沒有對任何已經計算出來的結果進行儲存和複用,因此上面這種思路是低效或者不符合要求的,應該使用動態規劃來解決問題。
動態規劃思想:先求簡單值在逐步遞推求複雜值,後面的值通過前面的結果來求得。
思路:求出到達每一個結點map[i][j]的最小路徑將其儲存在陣列dp[i][j]中,求任意dp[i][j]的值完全依賴於dp[i-1][j]和dp[i][j-1],因此先求出dp[][]陣列的第1行和第1列,然後從上到下,從左到右計算出每一個位置的結果值。
①建立一個二維陣列記錄每個位置的最小路徑dp[n][m];
②求出dp[][]中第1行和第1列的結果填充到dp[][]中;注意:在動態規劃問題中第1行和第1列需要手動求出,需要根據問題的要求進行求解,一般第1行和第1列的求解很簡單。
③從上到下,從左到右,通過二重迴圈求出任意dp[i][j]的結果填充到dp[][]中;注意:二重迴圈中i,j都是從1開始進行遍歷,即從矩陣第2行第2列的位置開始填充。
④最後dp[n-1][m-1]就是所求的結果。
import java.util.*; //矩陣最短路徑和問題:動態規劃4部曲 public class MinimumPath { public int getMin(int[][] map, int n, int m) { //特殊輸入 if(map==null||n<=0||m<=0) return 0; //①建立動態規劃結果矩陣dp[][] int[][] dp=new int[n][m]; //②求解第1行第1列的結果值 dp[0][0]=map[0][0]; for(int i=1;i<m;i++){ dp[0][i]=dp[0][i-1]+map[0][i]; } //求第1列的結果值 for(int i=1;i<n;i++){ dp[i][0]=dp[i-1][0]+map[i][0]; } //③從上到下,從左到右求任意dp[i][j] for(int i=1;i<n;i++){ for(int j=1;j<m;j++){ dp[i][j]=map[i][j]+Math.min(dp[i-1][j],dp[i][j-1]); } } //④返回右下角的結果值 return dp[n-1][m-1]; } }