1. 程式人生 > >[LeetCode] Minimum Falling Path Sum

[LeetCode] Minimum Falling Path Sum

首先這篇部落格本來在11月11日晚上就該發出來的。但是當時的我在圖書館,突然電腦抽風無線網路死活連不上,本來打算回到宿舍就把它發出來,可是回到宿舍之後忘記了。。因為回宿舍的路上發生了一點點事情。

1、題目

Given a square array of integers A, we want the minimum sum of a falling path through A.

A falling path starts at any element in the first row, and chooses one element from each row.  The next row's choice must be in a column that is different from the previous row's column by at most one.

 

Example 1:

Input: [[1,2,3],[4,5,6],[7,8,9]]
Output: 12
Explanation: 
The possible falling paths are:
  • [1,4,7], [1,4,8], [1,5,7], [1,5,8], [1,5,9]
  • [2,4,7], [2,4,8], [2,5,7], [2,5,8], [2,5,9], [2,6,8], [2,6,9]
  • [3,5,7], [3,5,8], [3,5,9], [3,6,8], [3,6,9]

The falling path with the smallest sum is [1,4,7]

, so the answer is 12.

2、分析

實際上求最大值或者最小值算是十分十分經典的動態規劃演算法了。在已知最值的基礎上建立新情況下的最值。這裡要求的是從第一行到達最後一行的最小值。每次能夠往下移動一行,但是列數相差最多為1。比如從位置(0,0)只能移動到(1,0)或者(1,1),從位置(0,1)可以移動到(1,0)(1,1)或者(1,2)。動態規劃思路很簡單:建立一個二維陣列dp,dp[i][j]表示到達位置(i,j)所需要的最小步數,題目要求的是到達最後一行的最小步數,那麼結果就是dp陣列最後一行的最小值。dp陣列的第一行的值和題目給出的陣列一樣。從第二行開始:dp[i][j] = A[i][j]+min(能夠到達A[i][j]的前三個位置)。比如:

dp[1][1] = A[1][1]+min(dp[0][0],dp[0][1],dp[0][2])。邊界條件自己寫程式碼的時候注意一下就好了。到達此位置的最小步數 = 從前一步移動到此位置的步數+到達前一步的最小步數。

3、程式碼

class Solution {
public:
    int minFallingPathSum(vector<vector<int>>& A) {
        int m = A.size();
        int n = A[0].size();
        int dp[m][n]={0};
        int mini = 0;
        for(int i=0;i<m;i++)
            mini+=A[i][0];
        for(int i=0;i<n;i++)
            dp[0][i] = A[0][i];
        for(int i=1;i<m;i++)
            for(int j=0;j<n;j++)
            {
                dp[i][j] = A[i][j]+min(dp[i-1][j-1<0?0:j-1],min(dp[i-1][j],dp[i-1][j+1>=n?n-1:j+1]));
                if(i==m-1&&dp[i][j]<mini) mini = dp[i][j];
            }
        return mini;
    }
};