leetcode 174. Dungeon Game (地牢游戏)

探讨一个关于地牢中营救公主的算法问题,骑士从左上角出发,目标是计算骑士顺利营救公主所需的最小初始血量。通过逆向思维,从公主位置开始,确保每一步骑士血量不低于1,最终得出初始所需血量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意大致如下:
有个地牢,公主(P)被关在右下角格子里,骑士(K)会从左上角格子进入营救公主,骑士初始有一个血量。每个格子中可能有怪兽,会减掉骑士的血量(负数),也可能有药水,会增加骑士的血量(正数)。骑士的血量一旦减到0或者0以下,就会挂掉。问骑士能顺利营救公主所需要的初始血量。骑士每次只会向右边或者下面移动

需要注意的是在左上角的格子和右下角的格子,也就是骑士刚进入的格子和公主所在的格子也可能会减少血量。
在这里插入图片描述
思路:
从公主所在的格子倒推回初始的格子,
因为骑士每次只会向右边或者下边移动,所以只需要取右边和下边的较小值即可。
右边界的情况只需要看下边的格子,下边界只需要看右边的格子。

但是需要注意几点:

  1. 骑士的血量一旦到达0或者0以下会挂掉,所以要保证每个格子的血量至少是1.
  2. 营救到公主的最后一刻,即到达右下角的时候也要保证活着见到公主,所以初始化最后一格血量的时候要保证至少是1
  3. 需要的血量也就是至少是1的血量 减去 地牢中的数字
    public int calculateMinimumHP(int[][] dungeon) {
        if(dungeon == null || dungeon.length == 0) {
            return 0;
        }
        
        int m = dungeon.length;
        int n = dungeon[0].length;
        
        int[][] dp = new int[m][n];
        //营救到公主的最后一刻也要保证血量至少是1
        dp[m-1][n-1] = Math.max(-dungeon[m-1][n-1] + 1, 1);
        
        //初始化右边界
        for(int i = m-2; i >= 0; i--) {
            dp[i][n-1] = Math.max(dp[i+1][n-1] - dungeon[i][n-1], 1);
        }
        //初始化下边界
        for(int j = n-2; j >= 0; j--) {
            dp[m-1][j] = Math.max(dp[m-1][j+1] - dungeon[m-1][j], 1);
        }
        
        for(int i = m-2; i >= 0; i--) {
            for(int j = n-2; j >= 0; j--) {
                //思路是取右边和下边的较小值,同时保证至少是1
                //但是为了减少计算量,取了简化版本
                //int right = Math.max(dp[i][j+1] - dungeon[i][j], 1);
                //int down = Math.max(dp[i+1][j] - dungeon[i][j], 1);
                //dp[i][j] = Math.min(right, down);
                dp[i][j] = Math.min(dp[i][j+1], dp[i+1][j]) - dungeon[i][j];
                dp[i][j] = Math.max(dp[i][j], 1);
            }
        }
        
        return dp[0][0];
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

蓝羽飞鸟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值