The demons had captured the princess (P) and imprisoned her in the bottom-right corner of a dungeon. The dungeon consists of M x N rooms
laid out in a 2D grid. Our valiant knight (K) was initially positioned in the top-left room and must fight his way through the dungeon to rescue the princess.The knight has an initial health point represented by a positive integer. If at any point his health point drops to 0 or below, he dies immediately.
Some of the rooms are guarded by demons, so the knight loses health (negative integers) upon entering these rooms; other rooms are either empty (0's) or contain magic orbs that increase the knight's health (positive integers).
In order to reach the princess as quickly as possible, the knight
decides to move only rightward or downward in each step.
本题为最小路径。在搜索的时候,保持最小值至少为1。
为了保证骑士可以最终到达,我们可以从终点逆向走到起点。每到一个地方有两种选择,向上或者向左。
选择需要初始血量最小的走法。matrix为正数表示是药水,骑士可以相应降低初始血量。为负数表明要增加血量来保证存活。
用二维空间来表示当前位置所需的最小血量,不断向左上方走直到起点。因为一个点只有两种走法,血量只与右边和下边有关。
我们可以减少空间到O(2n)。用来表示当前层与下一层。但是我们是逆向走,在dp[j+1]是已经是当前层,而dp[j]还停留在下一层未更新。所以我们只需一个O(n)空间就行了。
time: O(n^2), space: O(n)
public class Solution {
public int calculateMinimumHP(int[][] matrix) {
if(matrix == null || matrix.length == 0) return 0;
int m = matrix.length, n = matrix[0].length;
int[] dp = new int[n+1];
Arrays.fill(dp,Integer.MAX_VALUE);
dp[n-1] = 1;
for(int i=m-1;i>=0;i--) {
for(int j=n-1;j>=0;j--){
dp[j] = Math.max(1 , Math.min(dp[j],dp[j+1]) - matrix[i][j]);
} // dp[j] means go down, dp[j+1] means go right
}
return dp[0];
}
}
time: O(n^2), space: O(n^2)
public class Solution {
public int calculateMinimumHP(int[][] dungeon) {
int m = dungeon.length;
int n = dungeon[0].length;
//init dp table
int[][] h = new int[m][n];
h[m - 1][n - 1] = Math.max(1 - dungeon[m - 1][n - 1], 1);
//init last col
for (int i = m - 2; i >= 0; i--) {
h[i][n - 1] = Math.max(h[i + 1][n - 1] - dungeon[i][n - 1], 1);
}
//init last row
for (int j = n - 2; j >= 0; j--) {
h[m - 1][j] = Math.max(h[m - 1][j + 1] - dungeon[m - 1][j], 1);
}
//calculate dp table
for (int i = m - 2; i >= 0; i--) {
for (int j = n - 2; j >= 0; j--) {
int down = Math.max(h[i + 1][j] - dungeon[i][j], 1);
int right = Math.max(h[i][j + 1] - dungeon[i][j], 1);
h[i][j] = Math.min(right, down);
}
}
return h[0][0];
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。