LeetCode 174. 地下城游戏

题目链接:

力扣icon-default.png?t=M276https://leetcode-cn.com/problems/dungeon-game/

【分析】一看向下和向右走,第一反应肯定是dp了。但是如果从左上角开始dp的话,加血会影响我们判断当前的最低可维持血量,举个极端例子,arr[0][0] = -2,arr[0][1] = 100, arr[1][0] = 3,那么dp[1][1]是选择从(0,1)过来呢,还是从(1,0)过来呢,如果认为当前剩余血量越高越好的话,从100走来前面可能会有个-90之类的。也就是说右下角的状态受左和上的历史多个状态影响。

换种思路,如果从右下角开始看呢,例如样例中这个,dp[2][2] 至少为6,而dp[2][1] 处原始值为30,我们用6-30的到一个 <0 的值,所以这里的血量只要有1点就行了,dp[1][2]处为1,6-1=5,此处至少需要保持5点血量,所以可以发现,反向dp的话+的血量再多也只会使得最终结果为1而已,这样不会影响到向前dp的值。

所以得到的状态转移方程为dp[i][j] = max(min(dp[i][j - 1], dp[i - 1][j]) - arr[i][j]), 1)

class Solution {
    public int calculateMinimumHP(int[][] dungeon) {
        int m = dungeon.length, n = dungeon[0].length;
        int dp[][] = new int[m + 1][n + 1];
        dp[m - 1][n] = 1; dp[m][n - 1] = 1;
        int i, j;
        for(i = m - 1; i >= 0; i--){
            for(j = n - 1; j >= 0; j--){
                if(i == m - 1){
                    dp[i][j] = Math.max(dp[i][j + 1] - dungeon[i][j], 1); 
                }else if(j == n - 1){
                    dp[i][j] = Math.max(dp[i + 1][j] - dungeon[i][j], 1);
                }else{
                    dp[i][j] = Math.max(Math.min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j], 1);
                }
            }
        }
        return dp[0][0];
    }
}

你可能感兴趣的:(LeetCode,leetcode,动态规划)