今天我们看一道 leetcode hard 难度题目:地下城游戏。
恶魔们抓住了公主并将她关在了地下城 dungeon
的 右下角 。地下城是由 m x n
个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。
骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。
有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。
为了尽快解救公主,骑士决定每次只 向右 或 向下 移动一步。
返回确保骑士能够拯救到公主所需的最低初始健康点数。
注意:任何房间都可能对骑士的健康点数造成威胁,也可能增加骑士的健康点数,包括骑士进入的左上角房间以及公主被监禁的右下角房间。

输入:
dungeon = [[-2,-3,3],[-5,-10,1],[10,30,-5]]
输出:
7
解释:如果骑士遵循最佳路径:右 -> 右 -> 下 -> 下 ,则骑士的初始健康点数至少为 7 。
思考
挺像游戏的一道题,首先只能向下或向右移动,所以每个格子可以由上面或左边的格子移动而来,很自然想到可以用动态规划解决。
再想一想,该题必须遍历整个地下城而无法取巧,因为最低健康点数无法由局部数据算出,这是因为如果不把整个地下城走完,肯定不知道是否有更优路线。
动态规划
二维迷宫用两个变量 i
j
定位,其中 dp[i][j]
描述第 i
行 j
列所需的最低 HP。
但最低所需 HP 无法推断出是否能继续前进,我们还得知道当前 HP 才行,比如:
// 从左到右走
3 -> -5 -> 6 -> -9
在数字 6
的位置所需最低 HP 是 3
,但我们必须知道在 6
时勇者剩余 HP 才能判断 -9
会不会直接导致勇者挂了,因此我们将 dp[i][j]
结果定义为一个数组,第一项表示当前 HP