leetcode174.地下城游戏

题目:174.地下城游戏

class Solution {
    public int calculateMinimumHP(int[][] dungeon) {
    // 正向思维(自顶向下):走到任何一个位置时,血量都不能少于1并且到达终点时为1。
    // 最低初始健康点数(最小为1)a + 路径中血(增/减)逐个相加出现的最低值(负值)b >= 1
    // 但是从左上往右下的顺序注定a和b都会影响后续的决策。也就是说,这样的动态规划是不满足「无后效性」。
    // 逆向思维(自底向上):
    // 在每个路径上的点满足要求,最终求起点的血量,从终点(只剩1血)开始逐渐向左上角移动。由:
    // x-2 >= 1
    // x-2-3 >= 1
    // x-2-3+3 >= 1
    // x-2-3+3+1 >= 1
    // x-2-3+3+1-5 = 1 
    // 反过来:
    // x-2-3+3+1 = 1+5
    // x-2-3+3 = 1+5-1
    // x-2-3 = 1+5-1-3
    // x-2 = 1+5-1-3+3
    // x = 1+5-1-3+3+2 即 x = 7, 这样就无需考虑b且无后效性问题
    // dp[i][j] = max(min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j], 1)

        int m = dungeon.length;
        int n = dungeon[0].length;
        int[][] dp = new int[m+1][n+1];
        Arrays.fill(dp[m], Integer.MAX_VALUE); // 数组批量赋值,只能一位数组
        for(int j=0; j<=m; j++)
            dp[j][n] = Integer.MAX_VALUE;
        dp[m-1][n] = 1;
        dp[m][n-1] = 1;
        for(int i=m-1; i>=0; i--)
            for(int j=n-1; j>=0; j--)
                dp[i][j] = Math.max(Math.min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j], 1);
        return dp[0][0];
    }
}

看到一位网友的C++代码也很简洁:

class Solution {
public:
    int calculateMinimumHP(vector<vector<int>>& dungeon) {
        int n=dungeon.size(),m=dungeon[0].size();
        vector<vector<int>> dp(n+1,vector<int>(m+1,INT_MAX));
        dp[n][m-1]=dp[n-1][m]=1;
        for(int i=n-1;i>=0;i--){
            for(int j=m-1;j>=0;j--){
                dp[i][j]=max((min(dp[i+1][j],dp[i][j+1])-dungeon[i][j]),1);
            }
        }   
        return dp[0][0];
    }
};

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