题意:
解题思路:
1. 初始化公主节点的右侧跟下侧为1,这样就可以倒推算出到公主节点需要多少健康点数;
2. dp[i][j] = max(1, min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][i]);
3. dp[i][j]表示到(i, j)点需要最少的血量;
4. 方便计算多添加一行一列。使dp[n][m - 1] = 1, dp[m][m - 1] = 1;
PHP代码实现:
class Solution {
/**
* @param Integer[][] $dungeon
* @return Integer
*/
function calculateMinimumHP($dungeon) {
$m = count($dungeon);
$n = count($dungeon[0]);
$dp = array_fill(0, $m + 1, array_fill(0, $n + 1, PHP_INT_MAX));
$dp[$m - 1][$n] = 1;
$dp[$m][$n - 1] = 1;
for ($i = $m - 1; $i >= 0; $i--) {
for ($j = $n - 1; $j >= 0; $j --) {
//选最小的值作为要走的路
$minHp = min($dp[$i + 1][$j], $dp[$i][$j + 1]) - $dungeon[$i][$j];
if ($minHp < 1) {
$dp[$i][$j] = 1;
} else {
$dp[$i][$j] = $minHp;
}
}
}
return $dp[0][0];
}
}
go代码实现:
func calculateMinimumHP(dungeon [][]int) int {
m, n := len(dungeon), len(dungeon[0])
dp := make([][]int, m + 1)
for i := 0; i <= m; i++ {
dp[i] = make([]int, n + 1)
}
for i := 0; i <= m; i++ {
dp[i][n] = 1 << 31
}
for j := 0; j <= n; j++ {
dp[m][j] = 1 << 31
}
// 设置起点默认值。因为dp[m-1][n-1] = 1 - dungeon[m-1][n-1],可以反推到公主节点
dp[m][n - 1], dp[m - 1][n - 1] = 1, 1
for i := m - 1; i >= 0; i-- {
for j := n - 1; j >= 0; j-- {
minHp := min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j]
if minHp < 1 {
dp[i][j] = 1
} else {
dp[i][j] = minHp
}
}
}
return dp[0][0]
}
func min(x, y int) int {
if x < y {
return x
}
return y
}