/* * 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自己存活下来就好了 */