Java 动态规划 174. 地下城游戏

 代码展示:

class Solution {
    public int calculateMinimumHP(int[][] dungeon) {
        int m=dungeon.length;
        int n=dungeon[0].length;
        //创建dp数组
        int[][]dp=new int[m+1][n+1];
        //初始化
        for(int i=0;i<=m;i++){
            dp[i][n]=Integer.MAX_VALUE;
        }
        for(int j=0;j<=n;j++){
            dp[m][j]=Integer.MAX_VALUE;
        }
        dp[m-1][n]=1;dp[m][n-1]=1;
        //填充数组
        for(int i=m-1;i>=0;i--){
            for(int j=n-1;j>=0;j--){
                dp[i][j]=Math.min(dp[i][j+1],dp[i+1][j])-dungeon[i][j];
                dp[i][j]=Math.max(1,dp[i][j]);
            }
        }
        //返回值
        return dp[0][0];
    }
}

通过动态规划来解决这道题,根据动态规划的5大步骤分析解答

        1.状态表示

                通常来说,我们可以从前到后进行状态表示,也可以从后向前进行状态表示,

                从前到后进行状态表示的话我们可以设dp【i】【j】表示从起点到【i,j】位置时骑士的最小初始健康点

                从后向前进行状态表示的话我们可以设dp【i】【j】表示从【i,j】位置到终点位置骑士最小的初始健康点

                这里我们用第二种方式进行状态表示

        2.状态转移方程

                从最近的一步进行分析,我们要想从【i,j】位置到达终点位置,我们可以向右移动到【i,j+1】的位置,也可以向下移动到【i+1,j】的位置,而我们选择从哪里到终点呢,由于要求骑士的最低健康数,所以我们应该选择到达终点所需最低健康数低的那个位置去终点,而【i,j+1】,【i+1,j】的最低健康数即dp【i,j+1】,dp【i+1,j】,通过比较两个数的大小,选出小的那个位置

                所以状态转移方程应该为:dp[i][j]=Math.min(dp[i][j+1],dp[i+1][j])-dungeon[i][j];

dungeon[i][j]表示当前位置是加血还是扣血,要是加血,那么我们的初始血量就可以减少,要是扣血,那么我们的初始血量就要增加,所以是相反关系

        3.初始化

                为了方便初始化,我们要通过添加辅助结点的方式辅助初始化,在创建dp数组时,相对于dungeon数组,我们要多添加一行一列,这是动态规划常用的方法。

                要注意,填进辅助结点中的值要保证后续填表是正确的,通过分析,在对dp数组进行初始化时我们要将最后一行和最后一列除了 dp[m-1][n]和dp[m][n-1]设为1外,其余的都设为int类型的最大值

        4.填充数组

                由于dp【i,j】依靠dp【i,j+1】,dp【i+1,j】,所以行方向上采用从下往上,列方向上采用从右往左。

        5.返回值

                要知道从【0,0】位置到终点所需的最小健康值,所以返回dp【0】【0】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小林想被监督学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值