解法一:记忆化递归
如果想要求最小初始值,需要不断的递归从后面往前推。因为这样才能从最后的状态推导出一开始骑士最少需要多少血
int [][]memory;
public int calculateMinimumHP(int[][] dungeon) {
int m = dungeon.length;
int n = dungeon[0].length;
memory = new int[m][n];
for(int []row : memory){
Arrays.fill(row,-1);
}
return dp(dungeon,0,0);
}
public int dp(int [][]dungeon,int i,int j){
int m = dungeon.length;
int n = dungeon[0].length;
if(i == m - 1 && j == n - 1){
return dungeon[i][j] <= 0 ? 1 : 1 - dungeon[i][j];
}
if(i == m || j == n){
return Integer.MAX_VALUE;
}
if(memory[i][j] != -1){
return memory[i][j];
}
int count = Math.min(dp(dungeon,i+1,j),dp(dungeon,i,j+1)) - dungeon[i][j];
memory[i][j] = count >= 0 ? count : 1;
return memory[i][j];
}
解法二:迭代
public int calculateMinimumHP(int[][] dungeon) {
int m = dungeon.length;
int n = dungeon[0].length;
int[][] dp = new int[m][n];
for (int i = m - 1; i >= 0; i--) {
for (int j = n - 1; j >= 0; j--) {
if (i == m - 1 && j == n - 1) {
dp[i][j] = Math.max(1, 1 - dungeon[m - 1][n - 1]);
} else if (i == m - 1) {
dp[i][j] = Math.max(1, dp[i][j + 1] - dungeon[i][j]);
} else if (j == n - 1) {
dp[i][j] = Math.max(1, dp[i + 1][j] - dungeon[i][j]);
} else {
dp[i][j] = Math.max(1, Math.min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j]);
}
}
}
return dp[0][0];
}