给你一个 n x n
的 方形 整数数组 matrix
,请你找出并返回通过 matrix
的下降路径 的 最小和 。
下降路径 可以从第一行中的任何元素开始,并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列(即位于正下方或者沿对角线向左或者向右的第一个元素)。具体来说,位置 (row, col)
的下一个元素应当是 (row + 1, col - 1)
、(row + 1, col)
或者 (row + 1, col + 1)
。
示例 1:
输入:matrix = [[2,1,3],[6,5,4],[7,8,9]]
输出:13
解释:下面是两条和最小的下降路径,用加粗标注:
[[2,1,3], [[2,1,3],
[6,5,4], [6,5,4],
[7,8,9]] [7,8,9]]
示例 2:
输入:matrix = [[-19,57],[-40,-5]]
输出:-59
解释:下面是一条和最小的下降路径,用加粗标注:
[[-19,57],
[-40,-5]]
示例 3:
输入:matrix = [[-48]]
输出:-48
提示:
n == matrix.length
n == matrix[i].length
- 1 <=
n
<= 100 - -100 <=
matrix[i][j]
<= 100
思路
本题就是很经典的一道二维的动态规划(这里有个小技巧,一般碰到二维的dp,都建议倒推,否则正推容易出现所描述的状态没有无后效性,比如地下城游戏那道题目)。
所以设状态dp[i][j]
表示从(i,j)
这个点走到终点的最小路径和(本题的终点不固定,有多个,只要是矩阵的最后一行都可以是终点)。然后先初始化最后一行,因为终点的最小路径和就是它本身,然后再往上倒推,至于状态转移方程,题目都已经有所提示了:
dp[i][j] = min(dp[i+1][j-1], dp[i+1][j], dp[i+1][j+1])+matrix[i][j];
但是,为了防止出现数组越界访问的情况,要将第一个点和最后一个点做特殊处理。
最后,寻找dp矩阵第一层的最小值即可,就是我们要找的答案。
代码
public class Solution {
public int minFallingPathSum(int[][] matrix) {
int n = matrix.length;
int[][] dp = new int[n][n];//dp[i][j]表示从(i, j)->(终点)的最小路径和
for(int j=0;j<n;j++) {
dp[n-1][j] = matrix[n-1][j];//初始化最后一行
}
for(int i=n-2;i>=0;i--) {
for(int j=0;j<n;j++) {
if(j==0) {
dp[i][j] = Math.min(dp[i+1][j], dp[i+1][j+1])+matrix[i][j];
}
else if(j==n-1) {
dp[i][j] = Math.min(dp[i+1][j-1], dp[i+1][j])+matrix[i][j];
}
else {
dp[i][j] = Math.min(dp[i+1][j-1], Math.min(dp[i+1][j], dp[i+1][j+1]))+matrix[i][j];
}
}
}
int result = 123123123;
for(int j=0;j<n;j++) {
result = Math.min(result, dp[0][j]);//在第一行中寻找答案
}
return result;
}
}