题目链接

LeetCode 174. 地下城游戏[1]

题目描述

一些恶魔抓住了公主(P)并将她关在了地下城的右下角。地下城是由 M x N 个房间组成的二维网格。我们英勇的骑士(K)最初被安置在左上角的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。

骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。

有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。

为了尽快到达公主,骑士决定每次只向右或向下移动一步。

编写一个函数来计算确保骑士能够拯救到公主所需的最低初始健康点数。

例如,考虑到如下布局的地下城,如果骑士遵循最佳路径 右 -> 右 -> 下 -> 下,则骑士的初始健康点数至少为 7。

提示:

  • 骑士的健康点数没有上限。
  • 任何房间都可能对骑士的健康点数造成威胁,也可能增加骑士的健康点数,包括骑士进入的左上角房间以及公主被监禁的右下角房间。

题解

错误解法

首先我们肯定想到的是从左上到右下动态规划,那么对于 这个格子来说,它有两个选择,可以从 或者 过来。

我们令 表示从左上角走到 这个格子所需要的最小生命值,那么我们选择 ,也就是两个来向中较小的那个走过来。但是考虑了当前格子的数值之后,路线上所需生命的最小值是可能增大的,而这时候可能选择两个来向中较大的那个反而更好(因为那个来向数值之和比较大),所以这里就产生了矛盾,无法求解。

举个简单的例子:

这个例子中如果只看走到格子 的结果的话,肯定是 下 -> 右 -> 右 最好,因为这样初始生命只需要 2 就够了。而另一条路 右 -> 右 -> 下 则需要初始生命 3 。

但是如果继续走到格子 ,那么最优方向一定是从 过来(另一个方向负数太多)。但是到 的最优路线保存的是 下 -> 右 -> 右 这一条,走到终点总和是 -4 ,初始所需最小生命增大为 5 。而另一条原本不怎么好的路线 右 -> 右 -> 下 总和是 -2 ,初始所需最小生命 3 ,所以仍然保持不变。

这样看来原本不好的路线在最后的结果里是可能会变好的,所以不好保存下来直接递推。

正确解法

既然从左上到右下没法动态规划,我们不妨从右下到左上动态规划看看。

我们令 表示从 这个格子走到右下角所需要的最小生命值,同样我们选择两个去向中的较小值 。然后考虑了格子 之后, 就更新为:

为什么这里选择两个去向中所需初始生命较小的那个就没问题了呢?

严格证明

考虑上图这种情况,这里我把 抽象为了 ,右边一格抽象为了 ,右下角抽象为了 。然后 走下面这条路所需初始生命值最小,路径上格子记为 ,另一条路径上格子记为

因为走路径 所需的初始生命值更小,所以我们有:

等价于:

这时候我们在两边 里面同时加上 ,大小关系是不会变的。

而错误解法中,考虑下图这种情况:

同样我们可以得到:

到这里为止和上面正确解法是一模一样的。但是,加上 之后,和上面正解的区别就是,正解求和里每一项都加了,所以大小关系不变,但是错解只有一项加了(就是所有值全加起来),大小关系无法确定

代码

c++

        class Solution {public:int calculateMinimumHP(vector<vector<int>>& dungeon) {int n = dungeon.size(), m = dungeon[0].size();vector<vector<int>> dp(n+1, vector<int>(m+1, INT_MAX));dp[n][m-1] = dp[n-1][m] = 1;for (int i = n-1; i >= 0; --i) {for (int j = m-1; j >= 0; --j) {int minn = min(dp[i+1][j], dp[i][j+1]);dp[i][j] = max(1, minn-dungeon[i][j]);}}return dp[0][0];}
};

参考资料

[1]

LeetCode 174. 地下城游戏: https://leetcode-cn.com/problems/dungeon-game/

【每日算法Day 65】你能顺利救出地下城里的公主吗?相关推荐

  1. 【每日算法】C语言8大经典排序算法(2)

    接上文--->[每日算法]C语言8大经典排序算法(1) 二.插入类排序 插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子文件中 ...

  2. java回文数算法for_【Java】【每日算法/刷穿 LeetCode】9. 回文数(简单)

    首页 专栏 java 文章详情 0 [每日算法/刷穿 LeetCode]9. 回文数(简单) 宫水三叶发布于 今天 15:30 题目描述 判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从 ...

  3. 如何判断数组所有数都不等于一个数_【每日算法Day 91】求解数组中出现次数超过1/3的那个数

    题目链接 LeetCode 229. 求众数 II[1] 题目描述 给定一个大小为 的数组,找出其中所有出现超过 次的元素. 说明: 要求算法的时间复杂度为 ,空间复杂度为 . 示例1 输入: [3, ...

  4. 每日算法C语言1-求某整数

    每日算法C语言 题目 一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少? 程序分析: 在10万以内判断,先将该数加上100后再开方,再将该数加上168后再开方如 ...

  5. 消除左递归c++代码_【每日算法Day 85】图解算法:一行代码解决约瑟夫环的变体...

    题目链接 LeetCode 390. 消除游戏[1] 题目描述 给定一个从 到 排序的整数列表. 首先,从左到右,从第一个数字开始,每隔一个数字进行删除,直到列表的末尾. 第二步,在剩下的数字中,从右 ...

  6. 重复次数最多的 子串_每日算法系列【LeetCode 424】替换后的最长重复字符

    题目描述 给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次.在执行上述操作后,找到包含重复字母的最长子串的长度. 示例1 输入: s = &quo ...

  7. python 旋转矩阵_【每日算法Day 93】不用额外空间,你会旋转一个矩阵吗?

    第 100 天时,我可能会对这 100 天以来的算法题进行一个总结,然后暂时停止更新 LeetCode 题解了. 下一步可能更新 NLP 相关算法了,非常感谢大家每天的支持. 题目链接 LeetCod ...

  8. 每日算法刷题Day7-比较字符串大小,去掉多余的空格,单词替换

    ⭐每日算法题解系列文章旨在精选重点与易错的算法题,总结常见的算法思路与可能出现的错误,与笔者另一系列文章有所区别,并不是以知识点的形式提升算法能力,而是以实战习题的形式理解算法,使用算法.

  9. 每日算法(四十三)-java为了更改的规划城市,需要统计楼栋数目信息。

    每日算法(四十三)-java为了更改的规划城市,需要统计楼栋数目信息. 为了更改的规划城市,需要统计楼栋数目信息. 方法如下,一张航拍照片会被分隔为N*M个小格子,每个格子可以用0跟1来表示.如果楼栋 ...

  10. < 每日算法 - Javascript解析:经典弹珠游戏 >

    每日算法 - JavaScript解析:弹珠游戏 一.任务描述: > 示例一: >示例二 二.题意解析 三.解决方案: 往期内容

最新文章

  1. CSDN湘苗培优,遇见更好的自己
  2. 最小二乘法多项式曲线拟合原理与实现--转
  3. 雷达多普勒频率计算公式_手持式雷达流速仪的监测应用方案
  4. webstorm中配置svn
  5. 优化Neo4j Cypher查询
  6. 利用bootstrap框架做了一个采摘节节日活动网页
  7. 初识Python(二)
  8. Linux内核(4) - 内核学习的心理问题
  9. 工商管理专业知识与实务(中级)【4】
  10. linux查看 网卡信息
  11. Maxthon2.5.10.2576 beta苦菜花增强优化防假死正式版(1031)
  12. 《零秒工作》的一些总结
  13. Windows Home Server V2 Code Name Vail Preview
  14. 1919:【02NOIP普及组】选数
  15. Task 编程中的异常处理
  16. PPT插件(islide)
  17. 英特尔发布第三代全新可扩展处理器,加速5G网络转型
  18. 【外星眼halcon教程】没事别想不开做机器视觉工程师
  19. 旷视2022:以产品之能加速行业发展,以生态之力开拓AIoT蓝海
  20. 在r语言中使用GAM(广义相加模型)进行电力负荷时间序列分析

热门文章

  1. CMS 系统之 iframe 结构
  2. (转载)Linux上iptables防火墙的基本应用教程
  3. 【leetcode】数组的度-两个map关联初探
  4. jmeter(一)基础介绍
  5. [leedcode 169] Majority Element
  6. Codeforces 527C Glass Carving
  7. git卡在Resolving deltas 100%的解决办法
  8. js可以选择时间的日历控件
  9. (windows关灯模式/黑屏模式)专注于当前的工作窗口
  10. Java 设计模式 之 访问者模式