1. 程式人生 > >動態規劃3:矩陣最小路徑和問題

動態規劃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];
    }
}