1. 程式人生 > >Leetcode931. Minimum Falling Path Sum下降路徑最小和

Leetcode931. Minimum Falling Path Sum下降路徑最小和

給定一個方形整數陣列 A,我們想要得到通過 A 的下降路徑的最小和。

下降路徑可以從第一行中的任何元素開始,並從每一行中選擇一個元素。在下一行選擇的元素和當前行所選元素最多相隔一列。

 

示例:

輸入:[[1,2,3],[4,5,6],[7,8,9]] 輸出:12 解釋: 可能的下降路徑有:

  • [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]

和最小的下降路徑是 [1,4,7],所以答案是 12。

 

提示:

  1. 1 <= A.length == A[0].length <= 100
  2. -100 <= A[i][j] <= 100

 

典型的動態規劃

當前最好的狀態和上一層的狀態有關。

const int INF = INT_MAX;

class Solution {
public:
    int minFallingPathSum(vector<vector<int> >& A) 
    {
        int r = A.size();
        int c = A[0].size();
        vector<vector<int> > dp(r, vector<int>(c, INF));
        for(int i = 0; i < c; i++)
        {
            dp[0][i] = A[0][i];
        }
        for(int i = 1; i < r; i++)
        {
            for(int j = 0; j < c; j++)
            {
                if(j == 0)
                {
                    dp[i][j] = min(dp[i - 1][j], dp[i - 1][j + 1]) + A[i][j];
                }
                else if(j == c - 1)
                {
                    dp[i][j] = min(dp[i - 1][j], dp[i - 1][j - 1]) + A[i][j];
                }
                else
                {
                    dp[i][j] = min(dp[i - 1][j], min(dp[i - 1][j - 1], dp[i - 1][j + 1])) + A[i][j];
                }
            }
        }
        int ans = INF;
        for(int i = 0; i < c; i++)
        {
            ans = min(ans, dp[r - 1][i]);
        }
        return ans;
    }
};

因為當前索引的狀態只跟上一層的上一個索引狀態丶當前索引狀態丶下一個索引狀態有關。

用一個變數去維護上一層的上一個索引狀態,然後再從前往後開始遍歷。只需要一維的陣列空間就可以了。

優化後:

const int INF = INT_MAX;

class Solution {
public:
    int minFallingPathSum(vector<vector<int> >& A) 
    {
        int r = A.size();
        int c = A[0].size();
        vector<int> dp(c, INF);
        for(int i = 0; i < c; i++)
        {
            dp[i] = A[0][i];
        }
        for(int i = 1; i < r; i++)
        {
            int last = INF;
            for(int j = 0; j < c; j++)
            {
                if(j == 0)
                {
                    last = dp[j];
                    dp[j] = min(dp[j], dp[j + 1]) + A[i][j];
                }
                else if(j == c - 1)
                {
                    dp[j] = min(dp[j], last) + A[i][j];
                }
                else
                {
                    int temp = dp[j];
                    dp[j] = min(dp[j], min(last, dp[j + 1])) + A[i][j];
                    last = temp;
                }
            }
        }
        int ans = INF;
        for(int i = 0; i < c; i++)
        {
            ans = min(ans, dp[i]);
        }
        return ans;
    }
};