标签:
原题链接在这里:https://leetcode.com/problems/dungeon-game/
这是一道DP题,保存当前格到右下格所需要的最小体力,m*n的dp数组保存。
更新是Math.min(走右侧最小体力,左下侧最小体力). 走右侧最小体力 = Math.max(dp[i][j+1]- dungeon[i][j], 0). 假设一直dp[i][j+1] = 3, dungeon[i][j] = -5, 3-(-5) = 8是往右走所需的最小体力, 但若是dp[i][j+1] = 3, dungeon[i][j] = 8, 3-8 = -5, 当前吃的魔法豆加了8点体力,根本不需要最小体力值就可以往右走,所以所需最小体力为0. 往下走同理。
先出示右下角的点,再初始最后一行和最后一列。
Note: 1.最后返回的不是dp[0][0], 而是dp[0][0]加一,因为之前求得体力值的最小值是0, 但骑士的体力值必须是正数。
2. 之所以选择从后往前更新而不是从前往后更新是因为,从前往后更新时求得的局部最优不保证是全局最优。
AC Java:
1 public class Solution { 2 public int calculateMinimumHP(int[][] dungeon) { 3 if(dungeon == null || dungeon.length == 0 || dungeon[0].length == 0){ 4 return 0; 5 } 6 int m = dungeon.length; 7 int n = dungeon[0].length; 8 int [][] dp = new int[m][n]; 9 dp[m-1][n-1] = dungeon[m-1][n-1] < 0 ? -dungeon[m-1][n-1]:0; 10 for(int i = m-2; i>=0; i--){ 11 dp[i][n-1] = dp[i+1][n-1] - dungeon[i][n-1] > 0 ? dp[i+1][n-1] - dungeon[i][n-1] : 0; 12 } 13 for(int j = n-2; j>=0; j--){ 14 dp[m-1][j] = dp[m-1][j+1] - dungeon[m-1][j] > 0 ? dp[m-1][j+1] - dungeon[m-1][j] : 0; 15 } 16 for(int i = m-2; i>=0; i--){ 17 for(int j = n-2; j>=0; j--){ 18 dp[i][j] = Math.min((dp[i+1][j] - dungeon[i][j] > 0 ? dp[i+1][j] - dungeon[i][j]: 0), (dp[i][j+1] - dungeon[i][j] > 0 ? dp[i][j+1] - dungeon[i][j]: 0)); 19 } 20 } 21 return dp[0][0]+1; 22 } 23 }
标签:
原文地址:http://www.cnblogs.com/Dylan-Java-NYC/p/4827823.html