一些恶魔抓住了公主(P)并将她关在了地下城的右下角。地下城是由 M x N 个房间组成的二维网格。我们英勇的骑士(K)最初被安置在左上角的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。
骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。
有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。
为了尽快到达公主,骑士决定每次只向右或向下移动一步。
编写一个函数来计算确保骑士能够拯救到公主所需的最低初始健康点数。
例如,考虑到如下布局的地下城,如果骑士遵循最佳路径 右 -> 右 -> 下 -> 下,则骑士的初始健康点数至少为 7。
-2 (K) -3 3
-5 -10 1
10 30 -5 (P)
说明:
骑士的健康点数没有上限。
任何房间都可能对骑士的健康点数造成威胁,也可能增加骑士的健康点数,包括骑士进入的左上角房间以及公主被监禁的右下角房间。
通过次数15,803提交次数35,058
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/dungeon-game
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
动态规划,
class Solution:
def calculateMinimumHP(self, dungeon: List[List[int]]) -> int:
m = len(dungeon)
n = len(dungeon[0])
#建立状态转移数组、dp[i][j]代表到达这个位置需要最低血量值
dp = [[0]*n for _ in range(m)]
#初始化dp最后位置值(公主所在位置)
#最后位置如果为正,那么到达此位置所需血量只要保证为1就可以了
#如果最后位置为负,那么则需要保证血量减去这个负数最小为1
dp[-1][-1] = 1 if dungeon[-1][-1] >= 0 else -dungeon[-1][-1]+1
#遍历最后一列、从下向上
for i in range(m-2, -1, -1):
dp[i][-1] = dp[i+1][-1] - dungeon[i][-1]
#如果当前房间血量大于或等于下一层所需血量,那么这一层只需要1的血量就够了
if dp[i][-1] <= 0: dp[i][-1] = 1
#遍历最后一行、从右向左
for j in range(n-2, -1, -1):
dp[-1][j] = dp[-1][j+1] - dungeon[-1][j]
if dp[-1][j] <= 0: dp[-1][j] = 1
#其他情况
for i in range(m-2, -1, -1):
for j in range(n-2, -1, -1):
dp[i][j] = min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j]
if dp[i][j] <= 0: dp[i][j] = 1
return dp[0][0]