该篇将陆续收集动态规划一系列相关问题
1.Leetcode.931下降路径最小和
难度中等
给你一个 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:
输入:matrix = [[-19,57],[-40,-5]] 输出:-59 解释:如图所示,为和最小的下降路径
提示:
- n == matrix.length == matrix[i].length
- 1 <= n <= 100
-
1.1思路分析
仔细阅读题意,该题目要求我们求最小的路径和,这是一个很明显的求最值问题,
状态(一直在改变的量):最短路径和
- 选择(引起状态改变的动作):由
可知是当前位置的上方,左上和右上引起了当前位置的改变
- base case: i=0时(即第一行),所有列的元素是已知的为matrix[0][j]
我们要求最短的路径和,只需要对比上、左上和右上的路径长度,取最短的路径加上当前格子的路径长度。所以,我们设dp(matrix数组,行,列)函数,返回值为当前位置的最短路径。
1.2代码
1.2.1暴力递归
class Solution {
public int minFallingPathSum(int[][] matrix) {
int n=matrix.length;
int min=Integer.MAX_VALUE;
for(int j=0;j<n;j++){
min=Math.min(min,dp(matrix,n-1,j));
}
return min;
}
public static int dp(int[][] matrix,int i,int j){
if(i<0 || j<0 || i>=matrix.length || j>=matrix[0].length)
return 99999;
if(i==0)
return matrix[i][j];
return matrix[i][j]+min(
dp(matrix,i-1,j),
dp(matrix,i-1,j-1),
dp(matrix,i-1,j+1)
);
}
public static int min(int a,int b,int c){
return Math.min(a,Math.min(b,c));
}
}
1.2.2带备忘录的递归
class Solution {
int[][] memo;
public int minFallingPathSum(int[][] matrix) {
int n=matrix.length;
memo=new int[matrix.length][matrix[0].length];
for(int i=0;i<matrix.length;i++){
Arrays.fill(memo[i],66666);
}
int res=Integer.MAX_VALUE;
for(int j=0;j<matrix.length;j++){
res=Math.min(res,dp(matrix,n-1,j));
}
return res;
}
public int dp(int[][] matrix,int i,int j){
if(i<0 || j<0 || i>=matrix.length || j>=matrix[0].length)
return 99999;
if(i==0)
return matrix[0][j];
if(memo[i][j]!=66666)
return memo[i][j];
memo[i][j]=matrix[i][j]+min(
dp(matrix,i-1,j),
dp(matrix,i-1,j-1),
dp(matrix,i-1,j+1)
);
return memo[i][j];
}
int min(int a,int b,int c){
return Math.min(a,Math.min(b,c));
}
}