1. 程式人生 > 其它 >演算法——地下城遊戲(倒推DP)

演算法——地下城遊戲(倒推DP)

技術標籤:演算法動態規劃leetcodejava

一些惡魔抓住了公主(P)並將她關在了地下城的右下角。地下城是由 M x N 個房間組成的二維網格。我們英勇的騎士(K)最初被安置在左上角的房間裡,他必須穿過地下城並通過對抗惡魔來拯救公主。
騎士的初始健康點數為一個正整數。如果他的健康點數在某一時刻降至 0 或以下,他會立即死亡。
有些房間由惡魔守衛,因此騎士在進入這些房間時會失去健康點數(若房間裡的值為負整數,則表示騎士將損失健康點數);其他房間要麼是空的(房間裡的值為 0),要麼包含增加騎士健康點數的魔法球(若房間裡的值為正整數,則表示騎士將增加健康點數)。
為了儘快到達公主,騎士決定每次只向右或向下移動一步。

leetcode

解題思路:這是一道比較常規的倒推DP問題。

  • 正推的問題在於,有兩個重要的引數會影響後續的決策,自身血量和最低血量。也就是說,這樣的動態規劃是不滿足無後效性的。所以,如果採用倒推,則自身血量就不會影響到後續的決策,因為後面血量再多,也沒用。
  • 首先是狀態表示,利用一個二維陣列表示每個位置到終點的所需的最低血量。
  • 然後是狀態轉移,取右邊和下面兩個位置的中的最小值,再減去當前位置的值,就是當前位置所需的最低血量,當然,如果值大於1,那麼就將當前結果置為1。
class Solution {
    public int calculateMinimumHP(int[][] d) {
        int
n = d.length, m = d[0].length; int[][] f = new int[n + 1][m + 1]; for(int i = 0; i <= n; i++) { Arrays.fill(f[i], Integer.MAX_VALUE); } f[n][m - 1] = f[n - 1][m] = 1; for(int i = n - 1; i >= 0; i--) { for(int j = m - 1; j >= 0; j--
) { int min = Math.min(f[i + 1][j], f[i][j + 1]); f[i][j] = Math.max(min - d[i][j], 1); } } return f[0][0]; } }