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 (negative integers) upon entering these rooms; other rooms are either empty (0's) or contain magic orbs that increase the knight's health (positive integers).
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 least 7 if he follows the optimal path RIGHT-> 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.
题目大意:骑士从左上角的房间进入,想要救回位于右下角的公主,至少需要多少滴血。(在任意时刻,他的生命点数<= 0, 他会立刻死。),在每个房间他要么减血,要么回复。
思路:动态规划
我们定义dp[i][j]表示从位置(i, j)到从右下角成功活着出来至少需要多少滴血。假设右下角位置(m - 1, n - 1), 成功出来到达(m, n - 1) 或者 (m - 1, n)至少要有1滴血。dp[m][n - 1] = 1, dp[m - 1][n] = 1.
如果dungeon[m - 1][n - 1] < 0, dp[m - 1][n - 1] = min(dp[m][n - 1], dp[m - 1][n]) - dungeon[m - 1][n - 1],
否则 dp[m - 1][n - 1] = 1.
状态转移方程:dp[i][j] = min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j], if dungeon[i][j] <= 0
= 1, else dungeon[i][j] > 0
1 class Solution { 2 public: 3 int calculateMinimumHP(vector<vector<int>>& dungeon) { 4 int m = dungeon.size(); 5 if (m == 0) 6 return 1; 7 int n = dungeon[0].size(); 8 vector<vector<int> > dp(m + 1, vector<int>(n + 1, INT_MAX)); 9 dp[m][n - 1] = 1; 10 dp[m - 1][n] = 1; 11 for (int i = m - 1; i >= 0; i--) { 12 for (int j = n - 1; j >= 0; j--) { 13 int need = min(dp[i][j + 1], dp[i + 1][j]) - dungeon[i][j]; 14 dp[i][j] = need > 0 ? need : 1; 15 } 16 } 17 return dp[0][0]; 18 } 19 };