1. 程式人生 > 實用技巧 >[LeetCode] 174. Dungeon Game

[LeetCode] 174. Dungeon Game

The demons had captured the princess (P) and imprisoned her in the bottom-right corner of a dungeon. The dungeon consists of M x N rooms laid out in a 2D grid. Our valiant knight (K) was initially positioned in the top-left room and must fight his way through the dungeon to rescue the princess.

The knight has an initial health point represented by a positive integer. If at any point his health point drops to 0 or below, he dies immediately.

Some of the rooms are guarded by demons, so the knight loses health (negativeintegers) upon entering these rooms; other rooms are either empty (0's) or contain magic orbs that increase the knight's health (positiveintegers).

In order to reach the princess as quickly as possible, the knight decides to move only rightward or downward in each step.

Write a function to determine the knight's minimum initial health so that he is able to rescue the princess.

For example, given the dungeon below, the initial health of the knight must be at least7if he follows the optimal pathRIGHT-> RIGHT -> DOWN -> DOWN.

-2 (K) -3 3
-5 -10 1
10 30 -5 (P)

Note:

  • The knight's health has no upper bound.
  • Any room can contain threats or power-ups, even the first room the knight enters and the bottom-right room where the princess is imprisoned.

地下城遊戲。題意是一個騎士需要從左上角的點移動到右下角的點去營救公主。為了節省時間,他決定只往下走或者往右走。在移動過程中,房間裡面的數值會增加或者減少騎士的生命值,包括騎士一開始所處的房間和公主所處的房間。請返回騎士一開始最少需要的生命值以確保營救成功。

思路是動態規劃。這道題dp[i][j]的定義是當騎士到(i, j)座標時需要的最少生命值。一看到這道題目,就想到unique path型別的題目,但是這道題跟unique path的不同之處在於他給的是終點座標的值,問的是起始值。我們一般做的動態規劃的題目給的都是起始值,問的是終點座標的值。既然這道題問的是最少的生命值,所以我們可以像做其他DP題一樣,先建立一個二維陣列,並且把所有的座標都初始化為Integer.MAX_VALUE。這裡有兩處例外,就是dp[m - 1][n]和dp[m][n - 1],因為騎士在遇到終點dp[m][n]的時候,只會從這個點的上方或者左方過來,這兩個點的dp值起碼要等於1。接著從右下角往左上角掃描,每個點上的DP值是下方或者右方的一個較小的DP值 - 當前座標上的生命值,同時這個DP值不能小於1。

時間O(mn)

空間O(mn)

Java實現

 1 class Solution {
 2     public int calculateMinimumHP(int[][] dungeon) {
 3         // corner case
 4         if (dungeon == null || dungeon.length == 0) {
 5             return 0;
 6         }
 7 
 8         // normal case
 9         int m = dungeon.length;
10         int n = dungeon[0].length;
11         int[][] dp = new int[m + 1][n + 1];
12         for (int i = 0; i <= m; i++) {
13             Arrays.fill(dp[i], Integer.MAX_VALUE);
14         }
15         dp[m - 1][n] = 1;
16         dp[m][n - 1] = 1;
17         for (int i = m - 1; i >= 0; i--) {
18             for (int j = n - 1; j >= 0; j--) {
19                 int minHp = Math.min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j];
20                 if (minHp < 1) {
21                     dp[i][j] = 1;
22                 } else {
23                     dp[i][j] = minHp;
24                 }
25             }
26         }
27         return dp[0][0];
28     }
29 }

LeetCode 題目總結