Dungeon Game


Problem Statement :


The demons had captured the princess 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 was initially positioned in the top-left room and must fight his way through 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 (represented by negative integers), so the knight loses health upon entering these rooms; other rooms are either empty (represented as 0) or contain magic orbs that increase the knight's health (represented by positive integers).

To reach the princess as quickly as possible, the knight decides to move only rightward or downward in each step.

Return the knight's minimum initial health so that he can rescue the princess.

Note that any room can contain threats or power-ups, even the first room the knight enters and the bottom-right room where the princess is imprisoned.

 

Example 1:


Input: dungeon = [[-2,-3,3],[-5,-10,1],[10,30,-5]]
Output: 7
Explanation: The initial health of the knight must be at least 7 if he follows the optimal path: RIGHT-> RIGHT -> DOWN -> DOWN.
Example 2:

Input: dungeon = [[0]]
Output: 1
 

Constraints:

m == dungeon.length
n == dungeon[i].length
1 <= m, n <= 200
-1000 <= dungeon[i][j] <= 1000



Solution :



title-img


                            Solution in C :

int calculateMinimumHP(int** dungeon, int dungeonSize, int* dungeonColSize){
    int m = dungeonSize;
    int n = *dungeonColSize ;
    int** dp = malloc(m * sizeof(int*)) ;
    for(int i = 0; i < m; i++){
        dp[i] = malloc(n * sizeof(int)) ;
    }
    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] = 1 ;
            else if(i == m-1)
                dp[i][j] = dp[i][j+1] - dungeon[i][j+1] ;
            else if(j == n-1)
                dp[i][j] = dp[i+1][j] - dungeon[i+1][j] ;
            else
                dp[i][j] = fmin(dp[i][j+1] - dungeon[i][j+1] , dp[i+1][j] - dungeon[i+1][j]) ;
            dp[i][j] = fmax(1, dp[i][j]) ;
        }
    }
    int ret = dp[0][0] - dungeon[0][0] ;
    for(int i = 0; i < m; i++)
        free(dp[i]) ;
    free(dp) ;
    return fmax(ret , 1) ;
}
                        


                        Solution in C++ :

class Solution {
public:
    int solve (vector<vector<int>>& dungeon,vector<vector<int>>& dp,int i,int j,int m ,int n){
        if(i==m || j==n)
        return INT_MAX;

        if(i==m-1 && j==n-1)
        return dungeon[i][j]<=0 ? -dungeon[i][j]+1 : 1;

        if(dp[i][j]!=INT_MAX)
        return dp[i][j];

        int right = solve(dungeon,dp,i,j+1,m,n);
        int down = solve(dungeon,dp,i+1,j,m,n);

        int ans = min(right,down)-dungeon[i][j];

        return dp[i][j]= ans<=0?1:ans;

}
    int calculateMinimumHP(vector<vector<int>>& dungeon) {
        int m = dungeon.size();
        int n = dungeon[0].size();

        vector<vector<int>>dp(m+1,vector<int>(n+1,INT_MAX));

        return solve(dungeon,dp,0,0,m,n);
    }
};
                    


                        Solution in Java :

class Solution 
{   
    int[][] dp; int rows, cols;
    public int calculateMinimumHP(int[][] A)
    {
        rows = A.length; cols = A[0].length;
        dp = new int[rows][cols];
        
        calculateMinimumHPHelper(A, 0, 0);
        return dp[0][0];
    }
    public int calculateMinimumHPHelper(int[][] A, int i, int j)
    {
        if(i >= rows || j >= cols)
            return Integer.MAX_VALUE;
       
        if(dp[i][j] > 0)
            return dp[i][j];
            
        int leftPath = calculateMinimumHPHelper(A, i, j+ 1);
        int rightPath = calculateMinimumHPHelper(A, i + 1, j);
        
        if(leftPath == Integer.MAX_VALUE && rightPath == Integer.MAX_VALUE)
        {
            dp[i][j] = A[i][j] > 0 ? 1 : Math.abs(A[i][j]) + 1;
            return dp[i][j];
        }   
        int bestPath = Math.min(leftPath, rightPath);
        
        if(A[i][j] > 0)
            dp[i][j] = Math.max(bestPath - A[i][j], 1);
            
        else
            dp[i][j] = Math.abs(A[i][j]) + bestPath;
        
        return dp[i][j];
    }
}
                    


                        Solution in Python : 
                            
class Solution:
  def calculateMinimumHP(self, dungeon: List[List[int]]) -> int:
    m = len(dungeon)
    n = len(dungeon[0])
    dp = [math.inf] * (n + 1)
    dp[n - 1] = 1

    for i in reversed(range(m)):
      for j in reversed(range(n)):
        dp[j] = min(dp[j], dp[j + 1]) - dungeon[i][j]
        dp[j] = max(dp[j], 1)

    return dp[0]
                    


View More Similar Problems

Merge two sorted linked lists

This challenge is part of a tutorial track by MyCodeSchool Given pointers to the heads of two sorted linked lists, merge them into a single, sorted linked list. Either head pointer may be null meaning that the corresponding list is empty. Example headA refers to 1 -> 3 -> 7 -> NULL headB refers to 1 -> 2 -> NULL The new list is 1 -> 1 -> 2 -> 3 -> 7 -> NULL. Function Description C

View Solution →

Get Node Value

This challenge is part of a tutorial track by MyCodeSchool Given a pointer to the head of a linked list and a specific position, determine the data value at that position. Count backwards from the tail node. The tail is at postion 0, its parent is at 1 and so on. Example head refers to 3 -> 2 -> 1 -> 0 -> NULL positionFromTail = 2 Each of the data values matches its distance from the t

View Solution →

Delete duplicate-value nodes from a sorted linked list

This challenge is part of a tutorial track by MyCodeSchool You are given the pointer to the head node of a sorted linked list, where the data in the nodes is in ascending order. Delete nodes and return a sorted list with each distinct value in the original list. The given head pointer may be null indicating that the list is empty. Example head refers to the first node in the list 1 -> 2 -

View Solution →

Cycle Detection

A linked list is said to contain a cycle if any node is visited more than once while traversing the list. Given a pointer to the head of a linked list, determine if it contains a cycle. If it does, return 1. Otherwise, return 0. Example head refers 1 -> 2 -> 3 -> NUL The numbers shown are the node numbers, not their data values. There is no cycle in this list so return 0. head refer

View Solution →

Find Merge Point of Two Lists

This challenge is part of a tutorial track by MyCodeSchool Given pointers to the head nodes of 2 linked lists that merge together at some point, find the node where the two lists merge. The merge point is where both lists point to the same node, i.e. they reference the same memory location. It is guaranteed that the two head nodes will be different, and neither will be NULL. If the lists share

View Solution →

Inserting a Node Into a Sorted Doubly Linked List

Given a reference to the head of a doubly-linked list and an integer ,data , create a new DoublyLinkedListNode object having data value data and insert it at the proper location to maintain the sort. Example head refers to the list 1 <-> 2 <-> 4 - > NULL. data = 3 Return a reference to the new list: 1 <-> 2 <-> 4 - > NULL , Function Description Complete the sortedInsert function

View Solution →