174. Dungeon Game 地下城游戏
Title
一些惡魔抓住了公主(P)并將她關在了地下城的右下角。地下城是由 M x N 個房間組成的二維網格。我們英勇的騎士(K)最初被安置在左上角的房間里,他必須穿過地下城并通過對抗惡魔來拯救公主。
騎士的初始健康點數為一個正整數。如果他的健康點數在某一時刻降至 0 或以下,他會立即死亡。
有些房間由惡魔守衛,因此騎士在進入這些房間時會失去健康點數(若房間里的值為負整數,則表示騎士將損失健康點數);其他房間要么是空的(房間里的值為 0),要么包含增加騎士健康點數的魔法球(若房間里的值為正整數,則表示騎士將增加健康點數)。
為了盡快到達公主,騎士決定每次只向右或向下移動一步。
編寫一個函數來計算確保騎士能夠拯救到公主所需的最低初始健康點數。
例如,考慮到如下布局的地下城,如果騎士遵循最佳路徑 右 -> 右 -> 下 -> 下,則騎士的初始健康點數至少為 7。
| -5 | -10 | 1 |
| 10 | 30 | -5 § |
說明:
-
騎士的健康點數沒有上限。
-
任何房間都可能對騎士的健康點數造成威脅,也可能增加騎士的健康點數,包括騎士進入的左上角房間以及公主被監禁的右下角房間。
動態規劃
考慮從右下往左上進行動態規劃。令 dp[i][j] 表示從坐標 (i,j) 到終點所需的最小初始值。換句話說,當我們到達坐標 (i,j) 時,如果此時我們的路徑和不小于 dp[i][j] ,我們就能到達終點。
這樣一來,我們就無需擔心路徑和的問題,只需要關注最小初始值。對于 dp[i][j],我們只要關心 dp[i][j+1] 和 dp[i+1][j] 的最小值 minn。記當前格子的值為 dungeon(i,j),那么在坐標 (i,j) 的初始值只要達到 minn?dungeon(i,j) 即可。同時,初始值還必須大于等于 1。這樣我們就可以得到狀態轉移方程:
dp[i][j]=max(min(dp[i+1][j],dp[i][j+1])?dungeon(i,j),1)dp[i][j]=max(min(dp[i+1][j],dp[i][j+1])?dungeon(i,j),1)dp[i][j]=max(min(dp[i+1][j],dp[i][j+1])?dungeon(i,j),1)
最終答案即為 dp[0][0]。
邊界條件為,當 i=n-1 或者 j=m-1 時,dp[i][j] 轉移需要用到的 dp[i][j+1] 和 dp[i+1][j] 中有無效值,因此代碼實現中給無效值賦值為極大值。特別地,dp[n-1][m-1] 轉移需要用到的 dp[n?1][m] 和 dp[n][m-1] 均為無效值,因此我們給這兩個值賦值為 1。
Code
def calculateMinimumHP(self, dungeon: List[List[int]]) -> int:rows, cols = len(dungeon), len(dungeon[0])dp = [[10 ** 9] * (cols + 1) for _ in range(rows + 1)]dp[rows][cols -1] = dp[rows - 1][cols] = 1for i in range(rows - 1, -1, -1):for j in range(cols - 1, -1, -1):minn = min(dp[i + 1][j], dp[i][j + 1])dp[i][j] = max(minn - dungeon[i][j], 1)return dp[0][0]復雜度分析
時間復雜度:O(N×M),其中 N,M 為給定矩陣的長寬。
空間復雜度:O(N×M),其中 N,M 為給定矩陣的長寬,注意這里可以利用滾動數組進行優化,優化后空間復雜度可以達到 O(N)。
總結
以上是生活随笔為你收集整理的174. Dungeon Game 地下城游戏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高级指引——概念解释——图形 Shape
- 下一篇: 350. Intersection of