每天两道LeetCodeHard:(28)

139 阅读2分钟

174. Dungeon Game

二维数组,不dp都不好意思

题干:

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。

思考:

注意这个题是存在一个路径就行,而每个点只有两个来源。所以可以使用一个数组记录到达当前位置所需的最少血量dp1,一个数组记录最少时的剩余血量dp2,由此可以得到如下状态转移方程:(记住dp只和左,上,左上有关) 所以走过当前节点所需的最少血量=min(左侧所需最少血量+左侧差的血量,上边所需最少血量+上面差的血量) 差的血量是用对应剩余血量-当前所需要消耗的血量,如果当前剩余血量大于需要消耗的,那么就无需再补充了。 当前剩余血量=对应剩余血量-当前所需要的消耗量,需要补充,那么剩余血量为0 所以这个题需要根据不同的情况,更新对应的值。 好吧其实最根本的解法还是无脑寻找当前点和周围点的关系,然后找规律。 dp[i][j] = max(1, min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j]);

答案:

class Solution {
public:
    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] = 1; dp[m - 1][n] = 1;
        for (int i = m - 1; i >= 0; --i) {
            for (int j = n - 1; j >= 0; --j) {
                dp[i][j] = max(1, min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j]);
            }
        }
        return dp[0][0];
    }
};

答案补充:

dp类型的题目这个题真的可以说是很难了,想做题最好的办法是查表找规律,没法查的话就只能硬着想了。