1. 程式人生 > >leetcode64-Minimum Path Sum(最小路徑和)

leetcode64-Minimum Path Sum(最小路徑和)

問題描述:

Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.

Note: You can only move either down or right at any point in time.

給定一個 m * n 的網格,網格中有非負的數字。一個機器人要從左上角走到右下角,每次只能向下或向右移動一個位置,找出一條總和最小的路徑,返回最小值。

本題與leetcode62-Unique Paths相似。

問題求解:

典型的動態規劃題。動態規劃三要素:問題的階段,每個階段的狀態以及從前一個階段轉化到後一個階段之間的遞推關係。遞推關係必須是從次小的問題開始到較大問題之間的轉化,從這個角度來說,動態規劃往往可以用遞迴程式來實現,不過因為遞推可以充分利用前面儲存的子問題的解來減少重複計算,所以對於大規模問題來說,有遞迴不可比擬的優勢,這也是動態規劃演算法的核心之處。確定了動態規劃的這三要素,整個求解過程就可以用一個最優決策表來描述,最優決策表是一個二維表,其中行表示決策的階段,列表示問題狀態,表格需要填寫的資料一般對應此問題在某個階段某個狀態下的最優值(如最短路徑,最長公共子序列,最大價值等)

,填表的過程就是根據遞推關係,從1行1列開始,以行或者列優先的順序,依次填寫表格,最後根據整個表格的資料通過簡單的取捨或者運算求得問題的最優解。

首先找出遞推關係,比如設存放起點到每個格子 i,j 的最小路徑和的二維陣列為 MPS[i][j],遞推公式為:

MPS[i][j] = Min(MPS[i-1][j],MPS[i][j-1])+ grid[i][j];

格子 i,j 的MPS值可能有兩個來源:其左側格子 i,j-1 或者其上側格子 i-1,j ;取這兩個來源的較小MPS值,再加上當前格子的值 grid[i][j] 即為結果。!!!!

由於是從左上方向右下方走,故我們可以利用一個雙重迴圈來進行迭代計算,外層迴圈以行為單位,內層迴圈以列為單位,這樣可以利用已經計算好的階段 、狀態來計算當前格子的結果,因為每次計算某個格子時,其左側格子和上側格子結果已經算好,這也是動態規劃比遞迴要快的原因。

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>> minPathSum(grid);
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(i==0 || j==0)
                {//第一行或者第一列的情況
                    if(i==0) minPathSum[0][j] += minPathSum[0][j-1];
                    else minPathSum[i][0] += minPathSum[i-1][0];
                }
                else
                {//格子[i][j]的minPathSum值有兩個來源:左側格子[i][j-1],或上側格子[i-1][j].
                 //取兩者較小值,再加上當前格子的值grid[i][j] 即為結果
                    minPathSum[i][j] = min(minPathSum[i][j-1], minPathSum[i-1][j])+grid[i][j];
                }
            }
        }
        return minPathSum[m-1][n-1];
    }
};

空間複雜度為O(m * n),時間複雜度為O(m * n)。