力扣 地下城游戏

https://leetcode-cn.com/problems/dungeon-game/comments/

求从左上角到右下角至少需要的体力值,网格中加号减号,就是健康值。中通不允许为0 或者更小

 

-2      -3     3

-5     -10    1

10     30     -5

 

到终点至少要有1个体力值,我们可以反向dp推导。

 

if(终点) {
  //表示到终点那步至少需要保留的体力值

  dp[i][j] = max(1, 1-data[i][j])

}

 

if(最后一行) {
  当前格子只能从本行的后一个格子过来,所以

  就是后一个格子至少的体力值减当前格子消耗的体力值

  就是当前格子至少保留的体力值。

  dp[i][j] = max(1, dp[i][j+1]-data[i][j])

}

 

if(最后一列) {
  当前格子只能从本列的下一个格子过来,所以

  就是下一个格子至少的体力值减当前格子消耗的体力值

  就是当前格子至少保留的体力值。

  dp[i][j] = max(1, dp[i+1][j]-data[i][j])

}

其他情况:

// 当前格子可以从下一个格子过来,或者从后一个格子过来

我们要取使用最小的体力值,和1比较要去最大的体力值。

因为如果dp[i][j] 值为负的,说明在移动的过程中,当前获取的体力值,

足以将后面的步子走完,所以在这一步只需要保留活着就好。

也就是每次和1比较

package com.company;

public class DungeonGame {
    public static int calculateMinimumHP(int[][] dungeon) {
        int row = dungeon.length;
        int col = dungeon[0].length;
        int[][] dp = new int[row][col];

        for(int i = row - 1; i >= 0; i--) {
            for (int j = col - 1; j >= 0; j--) {
                if(i==row-1&&j==col-1) {
                    dp[i][j] = Math.max(1, 1-dungeon[i][j]);
                } else if (i == row - 1) {
                    dp[i][j] = Math.max(1,dp[i][j+1]-dungeon[i][j]);
                } else if (j == col - 1) {
                    dp[i][j] = Math.max(1, dp[i+1][j]-dungeon[i][j]);
                } else {
                    dp[i][j] = Math.max(1, Math.min(dp[i+1][j], dp[i][j+1])-dungeon[i][j]);
                }
            }
        }
        return dp[0][0];
    }

    public static void main(String[] args) {
        int[][] dungeon = {
            {-2, -3, 3},
            {-5, -10, 1},
            {10, 30, -5}
        };

        System.out.println(calculateMinimumHP(dungeon));
    }
}

 

posted @ 2021-05-26 17:30  姓蜀名黍  阅读(70)  评论(0)    收藏  举报