LeetCode 174 Dungeon Game
knight need to save the princess, and he needs to start from left top and the princess is at right bottom.
the knight has initial health point, and the rooms contains thing that can increase or decrease the health.
so we have to know the minimum initial health so he can rescue the princess without dead.
For grid problem like this, there is a higher possibility that it is a dp problem.
the tricky thing is: we have to make sure that each step this knight moves, the remaining health will be larger than 0.
so this problem is a reversed 2D dp:
dp[i][j] represents that the minimum health starting from i,j to row-1, col-1.
key equation:
dp[i][j] = Math.max(1, Math.min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j]);
so the minimum health we need starting from i,j to row-1, col-1, =
if (Math.min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j]) < 1, then that means we need dp[i][j] at least 1 to be alive
but what is the meaning of (Math.min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j]) < 1?
that means, we choose to go from either the path of i+1 to i, or j+1 to j, and of course we need to find the min of those two, becasue we need to get the cheapest way.
but in the same time, we need to initialize dp[row] and dp[col], but what should we use to initialize them?
because we need to find the min, so we have to initialize them with Integer.MAX_VALUE
but there are two places that we need to be more careful.
dp[m][n-1] and dp[m-1][n] should be 1, because for dp[m-1][n-1] should use Math.min(1,1) - dungeon[m-1][n-1] instead of Math.min(MAX_VALUE, MAX_VALUE) - dungeon[m-1][n-1] .
so the code will be:
class Solution {
public int calculateMinimumHP(int[][] dungeon) {
if (dungeon == null || dungeon.length == 0) {
return -1;
}
int m = dungeon.length;
int n = dungeon[0].length;
int[][] dp = new int[m + 1][n + 1];
for (int i = 0; i < m; i++) {
dp[i][n] = Integer.MAX_VALUE;
}
for (int i = 0; i < n; i++) {
dp[m][i] = Integer.MAX_VALUE;
}
dp[m-1][n] = 1;
dp[m][n-1] = 1;
for (int i = m - 1; i >= 0; i--) {
for (int j = n - 1; j >= 0; j--) {
if (Math.min(dp[i][j+1], dp[i+1][j]) - dungeon[i][j] > 1) { //如果还剩体力,就选择所需体力更小的那个路径
dp[i][j] = Math.min(dp[i][j+1], dp[i+1][j]) - dungeon[i][j];
} else { //如果没剩体力了 那么我们就必须在这儿重开,所需的最小初始体力为1
dp[i][j] = 1; //
}
}
}
return dp[0][0];
}
}

浙公网安备 33010602011771号