174. Dungeon Game

    /*
     * 174. Dungeon Game
     * 12.30 by Mingyang
     * dp[i][j]表示进入这个格子后保证knight不会死所需要的最小HP。
     * dp[i][j] is the minimum health value before he enters (i,j).
     * 如果一个格子的值为负,那么进入这个格子之前knight需要有的最小HP是-dungeon[i][j] + 1.如果格子的值非负,那么最小HP需求就是1.
     * 这里可以看出DP的方向是从最右下角开始一直到左上角。首先dp[m-1][n-1] = Math.max(1, -dungeon[m-1][n-1] + 1).
     * 递归方程是dp[i][j] = Math.max(1, Math.min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j]).
     */
    public int calculateMinimumHP(int[][] dungeon) {
        int m = dungeon.length;
        int n = dungeon[0].length;
        //init dp table
        int[][] dp = new int[m][n]; 
        dp[m - 1][n - 1] = Math.max(1 - dungeon[m - 1][n - 1], 1);     
        //init last row
        for (int i = m - 2; i >= 0; i--) {
            dp[i][n - 1] = Math.max(dp[i + 1][n - 1] - dungeon[i][n - 1], 1);
        } 
        //init last column
        for (int j = n - 2; j >= 0; j--) {
            dp[m - 1][j] = Math.max(dp[m - 1][j + 1] - dungeon[m - 1][j], 1);
        } 
        //calculate dp table
        for (int i = m - 2; i >= 0; i--) {
            for (int j = n - 2; j >= 0; j--) {
                int down = Math.max(dp[i + 1][j] - dungeon[i][j], 1);
                int right = Math.max(dp[i][j + 1] - dungeon[i][j], 1);
                dp[i][j] = Math.min(right, down);
            }
        } 
        return dp[0][0];
    }
    /*
     * 这里稍稍解释一下:dp[m - 1][j] = Math.max(dp[m - 1][j + 1] - dungeon[m - 1][j], 1);
     * 这个什么意思呢?如何dungeon使正的话就表示我会得到额外的血,所以我会减去这个东西,
     * 但是如果这个是负的,就表示我还要失去那么多血,所以最后的意思就是
     * 如果是负的就越加越大,那么我就需要有那么多钱才能活下来
     * 那么另一种情况就是,这个点很多补给,所以第一个减出来是负的,表示的意思是我只要1自己存活下来就好了
     */
原文地址:https://www.cnblogs.com/zmyvszk/p/5560167.html