[LeetCode] Dungeon Game

来源:互联网 发布:linux 安装jdk gz文件 编辑:程序博客网 时间:2024/06/05 19:11

题干:
The demons had captured the princess (P) 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 (K) was initially positioned in the top-left room and must fight his way through the 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, so the knight loses health (negative integers) upon entering these rooms; other rooms are either empty (0’s) or contain magic orbs that increase the knight’s health (positive integers).
In order to reach the princess as quickly as possible, the knight decides to move only rightward or downward in each step.
Write a function to determine the knight’s minimum initial health so that he is able to rescue the princess.

题目解析:
这道题目显然也是一道动态规划的题目,一开始的想法是从(0,0)位置开始,维护两个表格,一个当前位置剩余的血量,一个是到达当前位置需要的血量,然而由于维护的两个列表,有可能出现需要血量高,但是剩余血量也高的情况,就容易出现错误,因此第一次的尝试失败了,失败的代码如下:

class Solution {public:    int calculateMinimumHP(vector<vector<int>>& dungeon) {        int row = dungeon.size();        if (row == 0)            return 0;        int col = dungeon[0].size();        int need[row][col];        int left[row][col];        if (dungeon[0][0] < 0) {            left[0][0] = 1;            need[0][0] = 1 - dungeon[0][0];        } else {            need[0][0] = 1;            left[0][0] = 1 + dungeon[0][0];        }        for (int i = 1; i < row; i ++) {            if (left[i - 1][0] + dungeon[i][0] <= 0) {                left[i][0] = 1;                need[i][0] = need[i - 1][0] - left[i - 1][0] - dungeon[i][0] + 1;            } else {                left[i][0] = left[i - 1][0] + dungeon[i][0];                need[i][0] = need[i - 1][0];            }        }        for (int j = 1; j < col; j ++) {            if (left[0][j - 1] + dungeon[0][j] <= 0) {                left[0][j] = 1;                need[0][j] = need[0][j - 1] - left[0][j - 1] - dungeon[0][j] + 1;            } else {                left[0][j] = left[0][j - 1] + dungeon[0][j];                need[0][j] = need[0][j - 1];            }        }        for (int i = 1; i < row; i ++) {            for (int j = 1; j < col; j ++) {                int left1 = left[i - 1][j] + dungeon[i][j];                int need1;                if (left1 <= 0) {                    need1 = need[i - 1][j] - left1 + 1;                                } else {                    need1 = need[i - 1][j];                }                int left2 = left[i][j - 1] + dungeon[i][j];                int need2;                if (left2 <= 0) {                    need2 = need[i][j - 1] - left2 + 1;                } else {                    need2 = need[i][j - 1];                }                if (need1 > need2) {                    need[i][j] = need2;                    left[i][j] = max(1, left2);                } else if (need1 < need2) {                    need[i][j] = need1;                    left[i][j] = max(1, left1);                } else {                    need[i][j] = need1;                    int temp = max(left1, left2);                    left[i][j] = max(temp, 1);                }            }        }        return need[row - 1][col - 1];    }};

因此就要换一种方法进行计算,由于从(0,0)开始计算,维护的信息较多,因此第二次尝试从公主的房间,即右下角的房间开始,首先的初始值为max(1, 1 - dungeon[row - 1][col - 1]),维护一个表格hp[row][col],计算到达右下角的表格时当前位置需要的血量,递归式如下:hp[i][j] = max(1, min(hp[i + 1][j], hp[i][j + 1]) - dungeon[i][j]);最后成功的解决了这道题,AC代码如下:

class Solution {public:    int calculateMinimumHP(vector<vector<int>>& dungeon) {        int row = dungeon.size();        if (row == 0)            return 0;        int col = dungeon[0].size();        int hp[row][col];        hp[row - 1][col - 1] = max(1, 1 - dungeon[row - 1][col - 1]);        for (int i = row - 2; i >= 0; i --) {            hp[i][col - 1] = max(1, hp[i + 1][col - 1] - dungeon[i][col - 1]);        }        for (int j = col - 2; j >= 0; j --) {            hp[row - 1][j] = max(1, hp[row - 1][j + 1] - dungeon[row - 1][j]);        }        for (int i = row - 2; i >= 0; i --) {            for (int j = col - 2; j >= 0; j --) {                hp[i][j] = max(1, min(hp[i + 1][j], hp[i][j + 1]) - dungeon[i][j]);            }        }        return hp[0][0];    }};