dp[i][j]
表示:到达 [i, j]
位置,最小的下降路径dp[i][j]
[i-1, j-1]
到达 [i, j]
==> dp[i-1][j-1] + m[i][j]
[i-1, j]
到达 [i, j]
==> dp[i-1][j] + m[i][j]
[i-1, i+1]
到达 [i, j]
==> dp[i-1][j+1] + m[i][j]
dp[i][j] = min(上面三个) + m[i][j]
里面的值,要保证后面的填表是正确的
下标的映射
(0, 0)——>(1, 1)
在初始化的时候,可以把所有虚拟出的节点都设为
+∞
,然后将第一行改为0
就可以了
dp[m][n]
的值dp
表中最行一行的最小值public int minFallingPathSum(int[][] matrix) {
//1. 创建 dp 表
int n = matrix.length;
int[][] dp = new int[n+1][n+2];
//2. 初始化
for (int i = 1; i <= n; i++) {
//第一列和最后一列
dp[i][0] = dp[i][n+1] = Integer.MAX_VALUE;
}
//3. 填表
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
dp[i][j] = Math.min(dp[i-1][j],
Math.min(dp[i-1][j], dp[i-1][j+1])) + matrix[i-1][j-1];
}
}
int ret = Integer.MAX_VALUE;
for (int i = 1; i <= n; i++) {
ret = Math.min(ret, dp[n][i]);
}
return ret;
}
时间复杂度:
n*n
(两个for
循环) 空间复杂度:n*n
(弄了个二维dp
表)
dp[i][j]
表示:到达 [i, j]
位置时,最小路径和dp[i][j]
[i-1, j]
走过来==> dp[i-1][j] + g[i][j]
[i, j-1]
走过来==> dp[i][j-1] + g[i][j]
dp[0][1]
和 dp[1][0]
需要是 0dp[m][n]
public int minPathSum(int[][] grid) {
//1. 创建 dp 表
int m = grid.length;
int n = grid[0].length;
int[][] dp = new int[m+1][n+1];
//2. 初始化
for (int i = 0; i <= n; i++)
dp[0][i] = Integer.MAX_VALUE;
for (int i = 0; i <= m; i++)
dp[i][0] = Integer.MAX_VALUE;
dp[0][1] = dp[1][0] = 0;
//3. 填表
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]) + grid[i-1][j-1];
}
}
return dp[m][n];
}
dp[i][j]
表示:从 [i, j]
位置出发,到达终点,所需的最低初始健康点数这里不能以
[i, j]
为终点构建状态表示,
dp[i][j]
,此时的点数必须要>=下一个要到的地方 dp 值 x+d[i][j] >= dp[i][j+1]
,所以 x >= dp[i][j+1] - d[i][j]
即可x >= d[i+1][j] - d[i][j]
即可如果 d[i][j]
太大,就是说在那一格有个很大的血包。减完之后就变成一个负值了(你是一个负血的状态,通过这个格子之后也能顺利通过),这是不符合逻辑的。
dp[i][j]
和 1
放在一起取一下 max
我们关注的是格子的下面和右边的状态,所以可能会越界的是最下面一行和最右边一行
里面的值,需要保证后续的填表是正确的
1
点血量1
就可以了min
,我们只需要保证辅助的节点不被选上就可以,所以我们将其他的节点设为 +∞
dp[0][0]
public int calculateMinimumHP(int[][] dungeon) {
//1. 创建 dp 表
int m = dungeon.length;
int n = dungeon[0].length;
int[][] dp = new int[m+1][n+1];
//2. 初始化
for (int j = 0; j <= n; j++)
dp[m][j] = Integer.MAX_VALUE;
for (int i = 0; i <= m; i++)
dp[i][n] = Integer.MAX_VALUE;
dp[m][n-1] = dp[m-1][n] = 1;
//3. 填表
for (int i = m-1; i >= 0; i--) {
for (int j = n-1; j >= 0; j--) {
dp[i][j] = Math.min(dp[i][j+1], dp[i+1][j]) - dungeon[i][j];
dp[i][j] = Math.max(dp[i][j], 1);
}
}
return dp[0][0];
}