每日一题:地下城游戏

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

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

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

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

返回确保骑士能够拯救到公主所需的最低初始健康点数。

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

示例 1:

输入:dungeon = [[-2,-3,3],[-5,-10,1],[10,30,-5]]
输出:7
解释:如果骑士遵循最佳路径:右 -> 右 -> 下 -> 下 ,则骑士的初始健康点数至少为 7 。

示例 2:

输入:dungeon = [[0]]
输出:1

提示:

  • m == dungeon.length
  • n == dungeon[i].length
  • 1 <= m, n <= 200
  • -1000 <= dungeon[i][j] <= 1000

整体移动方向是从左上到右下,骑士走到第[i ,j]个格子需要的健康点数(血量)和第[i+1 ,j](下一步向右走)/ 第[i,j+1](下一步向下走)相关。因此很容易想到采取动态规划的方式。

正向dp

正向dp,即从王子(左上)向公主(右下)进行规划。先考虑如下这种简单情况:每个格子只扣除血量。

 计算dp[i,j]只需将dp[i+1,j]和dp[i,j+1]中更大的值加上当前[i,j]的值即可。

(注:上面描述的方式中dp中的值是负的,需要的血量取绝对值+1即可)

第一次dp:

第二次dp:

取得到了最终的需要血量 1 - 公主格子中的值 = 16点初始健康点。

 而题目中有的格子是可以回血(正)的。

在这种情况下我们继续考虑正向dp:

如上图所示,如果按照之前的思路,在 -3 和 -8 中我们将选择-3,但是在未来的格子中,存在-20这样一个炸弹值,因此实际上在 [0,0]处选择 -8 是全局最有解。也就是说:

即使知道了 dp[i+1,j]和 dp[i,j+1],也不能根据哪个大就挑哪个(上图第一步选择 -3 还是-8 )。因为有可能 dp[i+1,j] 处的耗血量大(-8),但后续全为加血。而 dp[i,j+1]甚至更深处 dp[i+1][j+1] 是更多的减血,选dp[i+1,j]才是全局最优

以上是比较感性的认知。理性的描述如下:

首先要理解后效性的概念。后效性是动态规划中的一个关键概念,它指一个问题的最优解可以通过其子问题的最优解来构造。换句话说,一个子问题的最优解不会影响其他子问题的最优解。

后效性提供了这点好处:简化了问题的求解,因为我们可以专注于子问题的最优解,而不用考虑它们之间的相互作用。

由于正值的存在,若从正向dp,后面的正值会影响到前面的判断,恰恰破坏了后效性。

考虑刚刚的正向dp,在这个过程其实需要维护两个值:当前所需最小初始生命值和到当前位置的路径和。我们希望需要的最初生命值尽量小,而到当前的路径和尽可能大,产生了两个重要程度相同的参数,正是这一点,破坏了后效性。

(也看到有的资料中描述动态规划是需要无后效性的,这里应该是描述差异,重点在于子问题间不要产生相互作用,也不要产生后向依赖,至于定义出的名词,没什么关系)

注意,也不是说这类问题正向dp完全不能做,可以通过记忆化搜索+动态规划+逻辑完善是可以解决的,但代价实在太大,并且不是最优解。

因而采取反向dp的方式。

继续以上面的例子分析为什么反向dp就不会产生后向依赖的问题?

按照反向dp,第一步结果如上图所示,注意,增加血量不能为之前的损失提供帮助,只会对后续有帮助。因此从在反向dp的过程中如果遇到了计算值 > 0,例如-5 + 30时,需要设置为0,因为你要想能到这个格子,前面扣除的血量是需要的,而不能用后面的加血预先抵扣前面的扣血。

以上只是分析过程,重复这个过程到左上角就不在这里赘述了。

接下来看dp数组的构造以及状态转移方程。

首先这里区分dp数组和原数组dungeon[i][j]的概念。

这是两个数组,虽然dp是依靠原数组计算出的,但分成两个数组看起来更清晰。

考虑问题输出结果:骑士需要的最小血量,注意骑士血量是不能为0的,0就死了,所以最小是1

那么走到dp[i,j]的血量和dp[i+1,j]还有dp[i,j+1]是什么关系?

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

注意这里就是区分原数组和dp数组的好处了,dp数组描述的是:从(i,j)出发,到达终点需要最少的血量。因此要取dp[i+1,j]和dp[i,j+1]中的较小值。而反映在dungeon数组中可能取的就是较大值。

接下来边界条件如何确定?因为起点是右下角,而到这里之后,骑士最低血是1,那么就外扩一行,并将右下格相邻的两个设为1。

而对于其他最外层格子,我们不需要使用到他们,因为dp取的是较小值,所以把他们都设为最大数就不会用到了。

 按上述公式填入对应值:

注意这里为什么是1,也就是公式外层为什么套一层max函数?

因为上文有提到:

按照反向dp,第一步结果如上图所示,注意,增加血量不能为之前的损失提供帮助,只会对后续有帮助。因此从在反向dp的过程中如果遇到了计算值 > 0,例如-5 + 30时,需要设置为0,因为你要想能到这个格子,前面扣除的血量是需要的,而不能用后面的加血预先抵扣前面的扣血。

当时所说设置为0只是在分析,而基于题目要求,骑士最小生命值为1。

进而完善整个dp数组,得到左上角骑士值7:

 代码:

class Solution {
public:int calculateMinimumHP(vector<vector<int>>& dungeon) {int n = dungeon.size(); int 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) {dp[i][j] = max(min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j], 1);}}return dp[0][0];}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/1596.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于非线性控制策略的电力电子电路——DC-DC电路的3种滑模控制器【MATLAB/simulink】

第一种&#xff0c;滞环滑模控制器Buck电路 在滑模控制系统中&#xff0c;采用滞环技术&#xff0c;直接将切换函数转换成开关控制信号&#xff0c;滞环技术被看做一种降低系统结构的切换频率的调制方法&#xff0c;业界也把基于滞环滑模技术实现的滑模控制称为直接滑模控制技…

分类网络总结

欢迎大家订阅我的专栏一起学习共同进步&#xff0c;主要针对25届应届毕业生 祝大家早日拿到offer&#xff01; lets go http://t.csdnimg.cn/dfcH3 目录 4. 经典分类网络与发展 4.1 AlexNet 4.2 VGGNet 4.3 GoogLeNet Inception 4.4 ResNet 4.5 DenseNet 4.6 MobileN…

Python基础04-操作系统中的文件与目录操作

在与操作系统交互时&#xff0c;我们经常需要执行文件和目录的操作。Python提供了丰富的库来帮助我们完成这些任务。以下是一些常见的操作&#xff0c;以及如何使用Python代码来实现它们。 1. 导航文件路径 在不同的操作系统中&#xff0c;文件路径的格式可能不同。Python的o…

提取出图像的感兴趣区域

这是我们的原图像 将图像的数值统计后进行条形图展示 import matplotlib.pyplot as plt from PIL import Image import numpy as np# 图像路径 image_path r"D:\My Data\Figure\OIP.jpg"# 打开图像 image Image.open(image_path)# 将图像转换为numpy数组 image_ar…

关于实验报告添加题注为0以及页面断层的解决办法

1.事情起源于最近在写实验报告和课设说明书时出现图的题注是图0-1等不遵循设置的章节标号&#xff0c;于是我在查询和个人尝试后发现必须设置多级编号并且自定义设置对应的样式为标题几 另外注意设置后必须题注也要设置对应的样式&#xff0c;否则还是0-1&#xff0c;不用编辑域…

全球30米100%水陆覆盖高程

数据是GIS的血液。 熟悉水经注的朋友都应该知道&#xff0c;我们可以为大家提供全球30米和全球12.5米的高程数据&#xff0c;但这两种数据都无法达到全球覆盖。 你可以从《40TB全球12.5米高程DEM原始数据》与《700G全球30米高程DEM原始数据》等文中了解这两种数据的详细说明。…

git简介及安装

Git | Git简介与安装 文章目录 Git | Git简介与安装一、Git简介二、Git安装Linux-centosLinux-ubuntu 一、Git简介 存在需求&#xff1a;对于一个文档&#xff0c;由于编写思路或者当前文档丢失&#xff0c;可能存在想要历史版本的需求&#xff0c;并且需要知道每个版本都修改了…

忘记宝塔账号密码 如何解决

cd /www/server/panel && btpython tools.py panel testpasswd参考 https://www.bt.cn/bbs/thread-1172-1-1.html

(C++) 树状数组

目录 一、介绍 二、一维树状数组 2.1 区间长度 2.2 前驱和后继 2.3 查询前缀和 2.4 点更新 三、一维数组的实现 3.1 区间长度函数 3.2 前缀和 3.3 插入/更新 3.4 封装成类 一、介绍 树状数组&#xff08;Binary Indexed Tree&#xff0c;BIT&#xff09;&#xff0c;又称为 …

39. UE5 RPG角色释放技能时转向目标方向

在上一篇&#xff0c;我们实现了火球术可以向目标方向发射&#xff0c;并且还可以按住Shift选择方向进行攻击。技能的问题解决&#xff0c;现在人物释放技能时&#xff0c;无法朝向目标方向&#xff0c;接下来我们解决人物的问题。 实现思路&#xff1a; 我们将使用一个官方的…

大一考核题解

在本篇中&#xff0c;将尽力使用多种解法&#xff0c;来达到一题多练的效果。 1&#xff1a; 1.原题链接&#xff1a; 238. 除自身以外数组的乘积 - 力扣&#xff08;LeetCode&#xff09; 这道题首先一眼肯定想到拿整体的积除以当前元素&#xff0c;将结果作为ans&#xff0c;…

Redis的主从复制

引入&#xff1a;分布是系统涉及到一个非常关键的问题&#xff1a;单点问题&#xff08;如果摸个服务器程序&#xff0c;只有一个节点&#xff08;只搞一个物理服务器&#xff0c;来部署这个服务器程序&#xff09;会出现&#xff1a; 1.可用性问题&#xff0c;如果这个机器挂…

轧铝机液压站比例阀控制器

轧铝机液压站是用于铝材轧制过程中提供动力和控制的系统&#xff0c;它对于确保铝材的质量至关重要。轧铝机液压站通常包含以下几个关键组成部分&#xff1a; 液压泵&#xff1a;为系统提供压力油&#xff0c;是液压系统的动力源。 控制阀组&#xff1a;包括方向控制阀、压力控…

由于磁盘空间不够导致服务无法访问的情况

昨天服务出现了一些“小状况”&#xff0c;这里做下记录&#xff0c;为了以后类似的问题&#xff0c;可以作为参考。 具体情况是&#xff0c;如下&#xff1a; 本来一直访问都好好的服务突然间访问不到了&#xff0c;首先确定了下服务器上的 docker 服务是否正常运行。确认正…

【触摸案例-触摸事件介绍 Objective-C语言】

一、触摸事件 1.接下来,我们来说这个,触摸事件, iOS当中的事件,可以分为三大类: 1)触摸事件 2)加速计事件 3)远程控制事件 事件呢,这个里面呢,使用app的过程当中呢,产生各种各样的事件,事件呢,分为三大类,在iOS里边儿啊,分为三大类,首先,有一个叫做触摸事…

MySQL中的“IS NULL”优化

MySQL中的“IS NULL”优化 在MySQL数据库中&#xff0c;查询性能的优化是保持应用高效运行的关键。一个常见的情况是处理空值&#xff08;NULL&#xff09;&#xff0c;尤其是在查询条件中使用IS NULL时。 理解IS NULL 在MySQL中&#xff0c;IS NULL运算符用于检查列中的值是…

2024年学浪视频怎么保存到本地相册

2024年已至&#xff0c;学浪应用上的视频购买人数持续攀升&#xff0c;然而一些课程已不再提供永久回放&#xff0c;这对那些在学浪购买了课程的人来说确实是一大困扰。在这里&#xff0c;我将为大家提供一种方法&#xff0c;让我们能够将学浪视频中那些非永久回放的内容下载到…

游戏录屏软件免费使用,超高清画质,让你爱不释手!

“最近迷上了一款动作冒险游戏&#xff0c;里面的剧情和打斗场面简直太燃了&#xff01;就想通过录屏的方式&#xff0c;把我自己的游戏过程保存下来。可是我发现市面上的录屏软件不是免费的就是功能有限&#xff0c;你们有没有用过什么好用又免费的游戏录屏软件啊&#xff1f;…

教科系统诗词大会竞赛活动方案

本次诗词大会竞赛由个人追逐赛、亲友团淘汰赛、冠军争霸赛三部分组成。 一、个人追逐赛 由每个参赛团选出一位挑战者&#xff0c;共六位挑战者首先参加个人追逐赛的比拼&#xff0c;每位挑战者最多可答九道题&#xff0c;题型可为识别诗句题、对句题、填字题&#xff0c;题目可…

【数据结构项目】通讯录

个人主页点这里~ 原文件在gitee里~ 通讯录的实现 基于动态顺序表实现通讯录项目1、功能要求2、代码实现file.hfile.cList.hList.ctest.c 基于动态顺序表实现通讯录项目 准备&#xff1a;结构体、动态内存管理、顺序表、文件操作 1、功能要求 ①能够存储100个人的通讯信息 ②…