给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
结合我们的做题步骤:
1).定义一个能够清楚描述最优子问题的数组(明确数组描述的含义)。
2).找出数组元素之间的关系式(状态转移方程)
3).找出初始值
按照步骤完成解题:
1.定义dp[i][j] 代表 从(0,0)到当前位置(i,j)路径和最小
2.我们知道dp[i][j]由 dp[i-1][j]或者dp[i][j-1]转移过来 由此我们可以得到状态转移方程: dp[i][j] = min(dp[i][j-1] , dp[i-1][j]) + grid[i][j];
3.初始化
for(int i = 1;i < row;i++)
dp[i][0] =dp[i-1][0] + grid[i][0];
for(int i = 1;i < col;i++)
dp[0][i] =dp[0][i-1] + grid[0][i];
优化
同我们之前做的DP一样,在求解的时候发现并不需要保存整个矩阵的状态,只需要当前行和当前列即可,同时又可以进一步优化,既dp[j]代表 从(0,0)走到第i行 j列位置上,最小的路径元素和。不用保存整个矩阵的状态,一维dp数组 迭代表示不同行上的路径累积和状态 ,于是状态转移方程编程:
dp[j] = Math.min(dp[j],dp[j-1]) + grid[i][j]; 其中Math.min()中的dp[j]标识i-1层的路径和状态 ,等号左边的dp[j]标识i行的状态
dp[0] = grid[0][0];
//初始化第0行的dp状态
for(int j = 1; j < col; j++){
dp[j] = dp[j-1] + grid[0][j];
}
for(int i = 1; i < row; i++){
//初始化第i行 0列的dp状态
dp[0] += grid[i][0] ;
for(int j = 1; j < col; j++){
dp[j] = Math.min(dp[j],dp[j-1]) + grid[i][j];
}
}