当前位置: 首页 > news >正文

174.地下城游戏——LeetCode

题目

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

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

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

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

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

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

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

解题思路

这个问题是一个典型的动态规划问题,我们需要找到从左上角到右下角的路径上,骑士所需的最小初始健康点数,使得在任何时候骑士的健康点数都不会降到0或以下。

动态规划的状态转移方程应该是这样的:

dp[i][j] 表示到达房间 (i, j) 时所需的最小生命值。由于骑士可以选择向下或向右移动,dp[i][j] 可以通过 dp[i+1][j](从上方房间来)或 dp[i][j+1](从左侧房间来)计算得出。我们需要考虑以下两种情况:

  1. 如果从上方房间 (i+1, j) 来,骑士需要在当前房间 (i, j) 至少剩余 dp[i+1][j] - dungeon[i+1][j] 生命值。
  2. 如果从左侧房间 (i, j+1) 来,骑士需要在当前房间 (i, j) 至少剩余 dp[i][j+1] - dungeon[i][j+1] 生命值。

我们需要取这两种情况中的较大者,因为骑士需要在进入房间前保证足够的生命值。然后,我们需要考虑当前房间 (i, j) 的效果 dungeon[i][j],如果 dungeon[i][j] 是负数,骑士将失去生命值。

因此,状态转移方程为:

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

解题过程

  1. 初始化 dp 数组,其大小与 dungeon 相同。

  2. 设置右下角的 dp 值,根据房间值决定初始健康点数。

  3. 从右下角开始向上和向左遍历 dungeon,填充 dp 数组。

  4. 对于每个格子 (i, j),计算从右边 (i, j+1) 和下面 (i+1, j) 到达的最小健康点数,并取较小者。

  5. 从计算结果中减去当前格子的值,确保结果至少为1(因为骑士不能有0或负的健康点数)。

  6. 循环结束后,dp[0][0] 就是所需的最小初始健康点数。

复杂度

  • 时间复杂度:O(m×n)O(m×n),其中 mn 分别是 dungeon 的行数和列数。我们需要遍历整个 dungeon

  • 空间复杂度:O(m×n)O(m×n),用于存储动态规划表 dp。如果只存储一行或一列的状态,可以优化到 O(min(m,n))O(min(m,n))。

Code

class Solution {public int calculateMinimumHP(int[][] dungeon) {final int m = dungeon.length, n = dungeon[0].length;int[][] dp = new int[m][n];// 初始化dp数组的右下角dp[m - 1][n - 1] = Math.max(1, 1 - dungeon[m - 1][n - 1]);// 从右下角开始向上和向左遍历for (int i = m - 2; i >= 0; i--) {dp[i][n - 1] = Math.max(1, dp[i + 1][n - 1] - dungeon[i][n - 1]);}for (int j = n - 2; j >= 0; j--) {dp[m - 1][j] = Math.max(1, dp[m - 1][j + 1] - dungeon[m - 1][j]);}// 动态规划填表for (int i = m - 2; i >= 0; i--) {for (int j = n - 2; j >= 0; j--) {// 取右边和下边的最小值,并减去当前房间的值dp[i][j] = Math.max(1, Math.min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j]);}}return dp[0][0];}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • [windows10]win10永久禁用系统自动更新操作方法
  • 职业生涯阶段总结3:转眼毕业三年
  • Vue路由入门学习
  • 【Java数据结构】---初始数据结构
  • solidity合约销毁(带销毁例子很常见)
  • 练习实践-基础设施:搭建时钟同步服务器-基于chrony软件在centos7系统上的实现
  • 学习STM32(1)--Keil软件安装与基本操作和Keil 软件高级应用
  • 来自echarts的灵感
  • 《Linux从入门到进阶》第一节 初识Linux
  • 科普文:JUC系列之ForkJoinPool源码解读ForkJoinWorkerThread
  • 悠易科技周文彪:创始人专注度很重要,一旦战略分散无法形成合力 | 中国广告营销行业资本报告深访④
  • LeetCode | 441 | 排列硬币 | 二分查找
  • 计算机组成原理 —— 指令流水线影响因素分类
  • 提示词工程
  • 微信小程序--实现地图定位---获取经纬度
  • 《深入 React 技术栈》
  • 2018天猫双11|这就是阿里云!不止有新技术,更有温暖的社会力量
  • bootstrap创建登录注册页面
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • Hibernate【inverse和cascade属性】知识要点
  • Java小白进阶笔记(3)-初级面向对象
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • Koa2 之文件上传下载
  • Python学习之路13-记分
  • scrapy学习之路4(itemloder的使用)
  • SOFAMosn配置模型
  • Terraform入门 - 1. 安装Terraform
  • vue:响应原理
  • WePY 在小程序性能调优上做出的探究
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 规范化安全开发 KOA 手脚架
  • 记一次用 NodeJs 实现模拟登录的思路
  • 网络应用优化——时延与带宽
  • 因为阿里,他们成了“杭漂”
  • 用 Swift 编写面向协议的视图
  • 原生 js 实现移动端 Touch 滑动反弹
  • 白色的风信子
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • 树莓派用上kodexplorer也能玩成私有网盘
  • # dbt source dbt source freshness命令详解
  • ### RabbitMQ五种工作模式:
  • #知识分享#笔记#学习方法
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (1)Hilt的基本概念和使用
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (每日一问)计算机网络:浏览器输入一个地址到跳出网页这个过程中发生了哪些事情?(废话少说版)
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)