Dungeon Game

hard array dp matrix

Problem

A knight starts at the top-left of a dungeon grid and must reach the princess at the bottom-right, moving only right or down. Each cell adds its value (negative for damage, positive for healing) to the knight's HP, which must stay ≥ 1 at all times. Return the minimum starting HP that guarantees a safe path.

Inputdungeon = [[-2,-3,3],[-5,-10,1],[10,30,-5]]
Output7
Going forward you don't know future demons. Solve backwards: at each cell compute the minimum HP needed to enter so that, after the cell's effect, you still have at least the required HP of the better neighbor.

def calculate_minimum_hp(dungeon):
    m, n = len(dungeon), len(dungeon[0])
    INF = float('inf')
    dp = [[INF] * (n + 1) for _ in range(m + 1)]
    dp[m][n - 1] = dp[m - 1][n] = 1
    for i in range(m - 1, -1, -1):
        for j in range(n - 1, -1, -1):
            need = min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j]
            dp[i][j] = max(1, need)
    return dp[0][0]
function calculateMinimumHP(dungeon) {
  const m = dungeon.length, n = dungeon[0].length;
  const INF = Infinity;
  const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(INF));
  dp[m][n - 1] = dp[m - 1][n] = 1;
  for (let i = m - 1; i >= 0; i--) {
    for (let j = n - 1; j >= 0; j--) {
      const need = Math.min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j];
      dp[i][j] = Math.max(1, need);
    }
  }
  return dp[0][0];
}
class Solution {
    public int calculateMinimumHP(int[][] dungeon) {
        int m = dungeon.length, n = dungeon[0].length;
        int[][] dp = new int[m + 1][n + 1];
        for (int[] r : dp) Arrays.fill(r, Integer.MAX_VALUE);
        dp[m][n - 1] = dp[m - 1][n] = 1;
        for (int i = m - 1; i >= 0; i--)
            for (int j = n - 1; j >= 0; j--) {
                int need = Math.min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j];
                dp[i][j] = Math.max(1, need);
            }
        return dp[0][0];
    }
}
int calculateMinimumHP(vector<vector<int>>& dungeon) {
    int m = dungeon.size(), n = dungeon[0].size();
    vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT_MAX));
    dp[m][n - 1] = dp[m - 1][n] = 1;
    for (int i = m - 1; i >= 0; i--)
        for (int j = n - 1; j >= 0; j--) {
            int need = min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j];
            dp[i][j] = max(1, need);
        }
    return dp[0][0];
}
Time: O(m·n) Space: O(m·n)