64.最小路径和
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
题解
DP问题一定要做分析
Step1. 确定最优子结构
即分析最优解所包含的子问题,是否也是最优的。
我们到达除了左侧和上侧边界的点,都由两种可能方式,从左到达或者从上到达。假设之前的步骤已经是最优的了,那么我们当前步骤只需要选择左侧或者上侧到达的最优值加上当前的值,那个最小就是该位置的最优值。
对于边界,第一行除了第一个位置,只能从左侧到达
第一列除了第一个位置,只能从上侧到达。
我们记每个点到达的最优值为 c [ i ] [ j ] c[i][j] c[i][j]
那么,我们可以表示为:
c
[
i
]
[
j
]
=
g
r
i
d
[
0
]
[
0
]
c[i][j]=grid[0][0]
c[i][j]=grid[0][0]
c [ i ] [ j ] = { c [ 0 ] [ j − 1 ] + g r i d [ 0 ] [ j ] , i = 0 , j > 0 c [ i − 1 ] [ 0 ] + g r i d [ i ] [ 0 ] , i > 0 , j = 0 max ( c [ i − 1 ] [ j ] , c [ i ] [ j − 1 ] ) + g r i d [ i ] [ j ] , i > 0 , j > 0 c[i][j] = \begin{cases} c[0][j-1]+grid[0][j], \quad i=0,j>0 \\ c[i-1][0]+grid[i][0], \quad i>0, j=0 \\ \max(c[i-1][j], c[i][j-1])+grid[i][j], \quad i>0,j>0 \end{cases} c[i][j]=⎩⎪⎨⎪⎧c[0][j−1]+grid[0][j],i=0,j>0c[i−1][0]+grid[i][0],i>0,j=0max(c[i−1][j],c[i][j−1])+grid[i][j],i>0,j>0
我们利用自底向上的编写思路:
class Solution {
public int minPathSum(int[][] grid) {
// 动态规划,自底向上
int rows = grid.length;
int cols = grid[0].length;
int [][] c = new int[rows][cols];
c[0][0] = grid[0][0];
//第一列,除grid[0][0]
for(int i = 1; i<rows; i++){
c[i][0] = c[i-1][0]+grid[i][0];
}
//第一行
for(int j=1; j<cols; j++){
c[0][j] = c[0][j-1] + grid[0][j];
}
//其余的
for(int i=1; i<rows; i++){
for(int j=1; j<cols;j++){
c[i][j] = Math.min(c[i-1][j], c[i][j-1]) + grid[i][j];
}
}
return c[rows-1][cols-1];
}
}