题目
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
.
Note:
1 <= A.length == A[0].length <= 100
-100 <= A[i][j] <= 100
题解一:DP
很明显可以用dp来解决此问题,记dp[j][i]
为从第一层计算到第j层并且走到了A[j][i]
这个位置的最小解。由于每次只能选择相邻的列,所以对于dp[j][i]
是由上一层相邻的三个状态继承而来,所以只要取上一层三个的最小值加到dp[j][i]
上就是新的状态,如图
可以得到状态方程为
dp[j][i] = min(dp[j-1][i-1],dp[j-1][i],dp[j-1][i+1])
特别地,对于边界的两个位置只需要考虑两个上一层状态的最小值,最后一行的最小值即为最优解。
同时又考虑到第j行的状态只与第j-1行有关,所以可以压缩数组,利用一个2*N的数组即可存储数据。
代码如下
class Solution {
public:
int minFallingPathSum(vector<vector<int>>& A) {
const int n = A[0].size();
vector<vector<int> >dp(2,vector<int>(n));
for (int i = 0;i<n;i++)
{
dp[0][i]=A[0][i];
}
for(int j = 1;j<n;j++)
{
dp[j%2][0] = A[j][0]+min(dp[(j-1)%2][0],dp[(j-1)%2][1]);
dp[j%2][n-1] = A[j][n-1]+min(dp[(j-1)%2][n-1],dp[(j-1)%2][n-2]);
for (int i = 1;i<n-1;i++)
{
dp[j%2][i]=A[j][i]+min(min(dp[(j-1)%2][i-1],dp[(j-1)%2][i]),dp[(j-1)%2][i+1]);
}
}
int m = dp[(n-1)%2][0];
for (int i = 0;i<n;i++)
{
if(m > dp[(n-1)%2][i])
m=dp[(n-1)%2][i];
}
return m ;
}
};