详解LeetCode地下城游戏(动态规划)——区分两种状态表示形式

地下城游戏

题目链接: 174. 地下城游戏

状态表示:

按照以往题的表示,dp[i][j]表示:从起点(0,0)位置到达(i,j)位置时,所需的最小初始健康值。但是如果这么去表示,不仅要考虑到达(i,j)位置的最小初始健康值,由于魔法球的存在,还需要考虑到达(i,j)位置时的健康值,因为魔法球会对算后续位置的最小初始健康值产生影响

下面用题目中的示例1为例,演示:

由此可知,到达魔法球位置所需的最低初始健康值和上一次的最低初始健康值保持一致,而魔法球会增加健康值,这就会对后面的结果产生影响,因此我们不仅要考虑到达(i,j)位置的最小初始健康值,还需要考虑到达(i,j)位置时的健康值,以保证后续结果的正确性

因此,我们可以试着用dp[i][j]表示:以(i,j)位置为起点,到达终点位置时,所需的最小健康值 。当(i,j)位置是魔法球时,可以用之前的dp[i+1][j]和dp[i][j+1]中的最小健康值减去治疗量,就能得到当前的位置到达终点位置时所需的最小健康值dp[i][j](注意:dp[i][j]不能小于0,最小值为1);当(i,j)位置是恶魔时,也是这样处理,实际上就是加上了需要扣除的健康值

通过这种状态表示,我们最终能够求得结果!

总结:

  1. 这道题的难点在于怎么去处理健康值增加的问题,健康值的增加不能为之前的损失提供帮助,只会对后续有帮助
  2. 如果按照第一种状态表示,dp[i][j]仅仅只表示了从(0,0)位置到达(i,j)位置所需的最小初始健康值,而由于魔法球的存在,导致后续的健康值会增加,因此我们还需要去记录当前位置的健康值,以保证后续计算最小初始健康值的正确性
  3. 如果按照第二种状态表示,dp[i][j]表示从(0,0)位置出发,按照最优路径到达(i,j)位置时,还需要剩余的最小健康值(为了到达终点后,健康值为1)。即dp[i][j]不仅表示了从(i,j)位置到达终点位置所需的最小初始健康值,还表示了从(0,0)位置出发到达(i,j)位置时,所需剩余的最小健康值(即当前健康值)
  4. 比较两种状态表示,可知,第二种表示更合理,更方便后续的填表

状态转移方程

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

初始化

创建表时,多创建一行(第m行)和一列(第n列),除dp[m][n-1] = 1(dp[m-1][n] 也可初始化为1,表示救出公主后还需剩余1点健康值),其他都初始化为正无穷(以防对填表产生影响)

填表顺序

从下往上,每一行从右往左

返回值

dp[0][0]

实现代码

java 复制代码
class Solution {
    public int calculateMinimumHP(int[][] dungeon) {
        //1.创建dp表
        int m = dungeon.length;
        int n = dungeon[0].length;
        int[][] dp = new int[m+1][n+1];

        //2.初始化
        for(int row = 0; row < m+1; row++) {
            dp[row][n] = Integer.MAX_VALUE;
        }
        for(int col = 0; col < n+1; col++) {
            dp[m][col] = Integer.MAX_VALUE;
        }
        dp[m][n-1] = 1;

        //3.填表
        for(int i = m-1; i >= 0; i--) {
            for(int j = n-1; j >= 0; j--) {
                dp[i][j] = Math.min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j];
                dp[i][j] = Math.max(1, dp[i][j]);
            }
        }
        //4.返回值
        return dp[0][0];
    }
}
相关推荐
zone77394 小时前
006:RAG 入门-面试官问你,RAG 为什么要切块?
后端·算法·面试
CoovallyAIHub6 小时前
OpenClaw 近 2000 个 Skills,为什么没有一个好用的视觉检测工具?
深度学习·算法·计算机视觉
CoovallyAIHub6 小时前
CVPR 2026 | 用一句话告诉 AI 分割什么——MedCLIPSeg 让医学图像分割不再需要海量标注
深度学习·算法·计算机视觉
CoovallyAIHub7 小时前
Claude Code 突然变成了 66 个专家?这个 5.8k Star 的开源项目,让我重新理解了什么叫"会用 AI"
深度学习·算法·计算机视觉
兆子龙7 小时前
前端哨兵模式(Sentinel Pattern):优雅实现无限滚动加载
前端·javascript·算法
xlp666hub10 小时前
Leetcode第五题:用C++解决盛最多水的容器问题
linux·c++·leetcode
CoovallyAIHub10 小时前
9个视觉语言模型工厂实测:Qwen 87.9%碾压全场,你的显卡能跑哪个?
算法
SparkX开源AI知识库11 小时前
手摸手带你安装OpenClaw并对接飞书
算法·架构
一语071611 小时前
3分钟搞懂深度学习AI:实操篇:卷积层
人工智能·算法