动态规划_174.地下城游戏(20200712)

// java
/**
1. 显然是动规问题,但正向动规是错的
2. 为什么?
3. 我来举个例子
4. 由于存在增加生命值的情况,恰如:
	4.1 路径 0 -> -1 -> 1 -> -1 -> -3 所需初始生命为 3 + 1
	4.2 路径 0 -> -2 -> 6 -> -1 -> -3 所需初始生命为 2 + 1
	4.3 显然路径 4.2 更优,但在正向动规过程中会选择 4.1
5. 所以我们使用反向动规 ?我们可以避免以上的情况
6. 状态转移方程 :
	6.1  needMin = Math.min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j];
    6.2  dp[i][j] = Math.max(0, needMin);
7. basecase:
	7.1 最后一个值: 正数无用(能走到一定满足), 顾要么是负数要么是0
	7.2 最后一列 needMin = dp[i + 1][colSize - 1] - dungeon[i][colSize - 1];
            	dp[i][colSize -1] = Math.max(0, needMin);
    7.3 最后一行 needMin = dp[rowSize - 1][i + 1] - dungeon[rowSize - 1][i];
            	dp[rowSize - 1][i] = Math.max(0, needMin);
*/
class Solution {
    public int calculateMinimumHP(int[][] dungeon) {
        if (dungeon == null || dungeon.length == 0 || dungeon[0].length == 0) {
            return 0;
        }
        int rowSize = dungeon.length;
        int colSize = dungeon[0].length;
        int[][] dp = new int[rowSize][colSize];
        // 设置最后一个值
        dp[rowSize - 1][colSize -1] = Math.max(0, -dungeon[rowSize - 1][colSize - 1]);

        // 设置最后一列的值
        for (int i = rowSize - 2; i >= 0; --i) {
            int needMin = dp[i + 1][colSize - 1] - dungeon[i][colSize - 1];
            dp[i][colSize -1] = Math.max(0, needMin);
        }

        // 设置最后一行的值
        for (int i = colSize - 2; i >= 0; --i) {
            int needMin = dp[rowSize - 1][i + 1] - dungeon[rowSize - 1][i];
            dp[rowSize - 1][i] = Math.max(0, needMin);
        }

        for (int i = rowSize - 2; i >= 0; --i) {
            for (int j = colSize - 2; j >= 0; --j) {
                // 从右边和下边选择一个最小值,然后减去当前的 dungeon 值
                int needMin = Math.min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j];
                dp[i][j] = Math.max(0, needMin);
            }
        }
        return dp[0][0] + 1;
    }
}

// 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) {
                int minn = min(dp[i + 1][j], dp[i][j + 1]);
                dp[i][j] = max(minn - dungeon[i][j], 1);
            }
        }
        return dp[0][0];
    }
};

你可能感兴趣的:(Miracle,wandering,in,LeetCode)