leetcode -- Dungeon Game -- dp重点,典型题

https://leetcode.com/problems/dungeon-game/

dp典型题目。table filling 问题,
跟这些一起看https://leetcode.com/problems/unique-paths/
https://leetcode.com/problems/minimum-path-sum/

这里dp[i][j] 要从dp[len(n)][len(m)]开始递推,dp[0][0]才是最后的结果。因为0 -> -300 -> 310 -> 0 和 0 -> -1 -> 2 -> 0。这两条路径的净HP收益分别是-300 + 310 = 10 与 -1 + 2 = 1。第一条路径的净收益更高,但是它所需的初始HP至少是301,才能抵消第二个房间的-300HP损失,而第二条路径只需要初始HP为2就可以了。

下面的D[i][j]表示至少要多少hp才能从(i,j)到达右下角

乍一看,这个问题和”Maximum/Minimum Path Sum”问题很相似。然而,具有全局最大HP(生命值)收益的路径并不一定可以保证最小的初始HP,因为题目中具有限制条件:HP不能≤0。例如,考虑下面的两条路径:0 -> -300 -> 310 -> 0 和 0 -> -1 -> 2 -> 0。这两条路径的净HP收益分别是-300 + 310 = 10 与 -1 + 2 = 1。第一条路径的净收益更高,但是它所需的初始HP至少是301,才能抵消第二个房间的-300HP损失,而第二条路径只需要初始HP为2就可以了。

幸运的是,这个问题可以通过“table-filling”(表格填充)动态规划算法解决,与其他”grid walking”(格子行走)问题类似:

首先,我们应该维护一个2维数组D,与地牢数组的大小相同,其中D[i][j]代表可以保证骑士在进入房间(i,j)之前,探索其余地牢时能够存活下来的最小HP。显然D[0][0]就是我们随后需要的最终答案。因此,对于这个问题,我们需要从右下角到左上角填充表格。

然后,我们来计算离开房间(i,j)时的最小HP。从这一点出发只有两条路径可选:(i + 1, j)和(i, j + 1)。当然我们会选择拥有更小D值的那个房间,换言之,骑士完成剩下的旅途所需的较小HP。因此我们有:

  min_HP_on_exit = min(D[i+1][j], D[i][j+1])

现在D[i][j]可以通过dungeon[i][j]和min_HP_on_exit,根据下面的情景得出:

如果dungeon[i][j] == 0,那么在这个房间里很安全。 骑士离开这个房间时的HP和他进入房间时的HP保持一致, 也就是说 D[i][j] = min_HP_on_exit.

如果dungeon[i][j] < 0,那么骑士在进入该房间之前的HP > 离开房间时的HP,min_HP_on_exit才能抵消他在该房间中的HP损失。 最小HP花费就是 “-dungeon[i][j]”, 因此我们有公式 D[i][j] = min_HP_on_exit - dungeon[i][j].

如果dungeon[i][j] > 0, 那么骑士在进入房间(i, j) 时的HP只需为min_HP_on_exit - dungeon[i][j],因为他可以在该房间内获得数值为”dungeon[i][j]”的HP收益。 不过,这种情况下min_HP_on_exit - dungeon[i][j]的数值可能≤0。 此时,我们需要把值置为1以确保D[i][j]为正整数: D[i][j] = max(min_HP_on_exit - dungeon[i][j], 1)。例如,dungeon[i][j] = 30, min_HP_on_exit = 100, 那么我们只需要70就行了。但是如果dungeon[i][j] = 300, min_HP_on_exit = 100, 我们只需要1就够了

注意 dungeon[i][j] > 0 条件下的等式实际上可以覆盖其他两种情况。 因此我们可以把三种情况归纳为同一个等式: 亦即:

D[i][j] = max(min_HP_on_exit - dungeon[i][j], 1)
dungeon[i][j]可以为任意值。

D[0][0]就是最终答案。 此外,像许多其他”table-filling”问题一样,二维数组D可以用一维滚动数组替代。

参考http://bookshadow.com/weblog/2015/01/07/leetcode-dungeon-game/的思路和code

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值