题意:

image.png

解题思路:

  1. 1. 初始化公主节点的右侧跟下侧为1,这样就可以倒推算出到公主节点需要多少健康点数;
  2. 2. dp[i][j] = max(1, min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][i]);
  3. 3. dp[i][j]表示到(i, j)点需要最少的血量;
  4. 4. 方便计算多添加一行一列。使dp[n][m - 1] = 1, dp[m][m - 1] = 1;

PHP代码实现:

  1. class Solution {
  2. /**
  3. * @param Integer[][] $dungeon
  4. * @return Integer
  5. */
  6. function calculateMinimumHP($dungeon) {
  7. $m = count($dungeon);
  8. $n = count($dungeon[0]);
  9. $dp = array_fill(0, $m + 1, array_fill(0, $n + 1, PHP_INT_MAX));
  10. $dp[$m - 1][$n] = 1;
  11. $dp[$m][$n - 1] = 1;
  12. for ($i = $m - 1; $i >= 0; $i--) {
  13. for ($j = $n - 1; $j >= 0; $j --) {
  14. //选最小的值作为要走的路
  15. $minHp = min($dp[$i + 1][$j], $dp[$i][$j + 1]) - $dungeon[$i][$j];
  16. if ($minHp < 1) {
  17. $dp[$i][$j] = 1;
  18. } else {
  19. $dp[$i][$j] = $minHp;
  20. }
  21. }
  22. }
  23. return $dp[0][0];
  24. }
  25. }

go代码实现:

  1. func calculateMinimumHP(dungeon [][]int) int {
  2. m, n := len(dungeon), len(dungeon[0])
  3. dp := make([][]int, m + 1)
  4. for i := 0; i <= m; i++ {
  5. dp[i] = make([]int, n + 1)
  6. }
  7. for i := 0; i <= m; i++ {
  8. dp[i][n] = 1 << 31
  9. }
  10. for j := 0; j <= n; j++ {
  11. dp[m][j] = 1 << 31
  12. }
  13. // 设置起点默认值。因为dp[m-1][n-1] = 1 - dungeon[m-1][n-1],可以反推到公主节点
  14. dp[m][n - 1], dp[m - 1][n - 1] = 1, 1
  15. for i := m - 1; i >= 0; i-- {
  16. for j := n - 1; j >= 0; j-- {
  17. minHp := min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j]
  18. if minHp < 1 {
  19. dp[i][j] = 1
  20. } else {
  21. dp[i][j] = minHp
  22. }
  23. }
  24. }
  25. return dp[0][0]
  26. }
  27. func min(x, y int) int {
  28. if x < y {
  29. return x
  30. }
  31. return y
  32. }