地下城游戏被描述为:
恶魔抓住了公主(P)并将她关进监狱 在地牢的右下角。 Ť 他的地牢包含了以2D网格布局的M x N个房间。 我们英勇的骑士(K)最初位于左上角的房间里 并且必须通过地牢来拯救公主。骑士的初始健康点由正整数表示。 如果他的健康点在任何时候降至0或以下,他会立即死亡。
部分房间被恶魔守卫, 所以骑士进入这些房间后会失去健康(负整数); 其他房间要么是空的(0' s),要么包含增加骑士健康的魔法球(正整数)。
为了尽快到达公主, 骑士决定在每一步中只向右或向下移动。
编写一个函数来确定骑士的最低初始健康状况 这样他就能救出公主。
例如,考虑到下面的地牢,最初的健康状况 如果骑士遵循最佳路径RIGHT->,则骑士必须至少为7。右 - >向下 - > DOWN。
注意:
骑士的健康没有上限。 任何房间都可以包含威胁或加电,即使是骑士进入的第一个房间 以及公主被监禁的右下方房间。
示例:
dungeon = [[-2, -3, 4],
[-6, -15, 0],
[10, 25, -6]]
答案:8
代码解决方案是:
def dungeonGame(dungeon):
dp = [float("inf") for _ in dungeon[0]]
dp[-1] = 1
for i in reversed(range(len(dungeon))):
dp[-1] = max(dp[-1] - dungeon[i][-1], 1)
for j in reversed(range(len(dungeon[i]) - 1)):
min_HP_on_exit = min(dp[j], dp[j + 1])
dp[j] = max(min_HP_on_exit - dungeon[i][j], 1)
return dp[0]
有人可以解释上述解决方案是如何运作的吗?为什么dp仅提供示例中的len 3?是因为只需要3个步骤,不包括开始和结束房间?为什么它在相邻的dp上达到最小值,然后达到最大值?另外,自从dungeon [i] [j]以来,最后一列似乎没有被考虑,其中j仅上升到1(采用给定的示例矩阵)。我知道解决方案写得很好,只是想了解它如何考虑所有路径。
答案 0 :(得分:2)
此算法从右下方向后移动,向左然后向上,找到沿途每一步的最佳得分。我建议您使用笔和纸执行算法,记下沿途的i,j和dp的当前值。这应该真的很清楚。
(开始):没有我,没有j,dp = [inf inf 1]
为了获胜,你需要至少1 HP才能获胜。
(进入第一个循环后):i = 2,dp = [inf inf 7]。
你需要7点生命才能在右下方的-6中生存下来。
(进入内循环后):i = 2,j = 1,dp = [inf 1 7]
如果你位于底部中心的正方形,那么最小的1个生命值就足以在该正方形的+25上生存,并到达需要至少7的相邻正方形。依此类推。
这是在右转(存储在中间结果的下一个元素library(ggplot2)
library(grid)
library(gtable)
p = ggplot(mpg, aes(cty, hwy, color = factor(year))) +
geom_point() +
facet_wrap(~ cyl, nrow = 1)
gt <- ggplotGrob(p)
panels = subset(gt$layout, grepl("panel", gt$layout$name), t:r)
# The span of the vertical gap
Bmin = min(panels$t) - 1
Bmax = max(panels$t)
# The columns of the gaps (two to the right of the panels
cols = unique(panels$r)[-length(unique(panels$r))] + 2
# The grob - grey rectangle
g = rectGrob(gp = gpar(col = NA, fill = "grey40"))
## Add greyrectangles into the vertical gaps
gt <- gtable_add_grob(gt,
rep(list(g), length(cols)),
t=Bmin, l=cols, b=Bmax)
## Draw it
grid.newpage()
grid.draw(gt)
)或向下,dp[j + 1]
之间选择的关键线。
dp[j]
中间结果只有三个元素,因为移动规则(仅向右和向下移动)和对角线为3的地牢,最多只有3个地方可以在任意数量的移动之后。
每当求解器向上移动一行时,最后一列将作为一个特例来处理:
min_HP_on_exit = min(dp[j], dp[j + 1])
为什么呢?嗯,它与其他专栏的不同之处在于你无法向右移动,只能向下移动。