174. Dungeon Game

问题:

勇士救公主问题。

勇士从左上角[0,0]出发,要到达右下角[n-1,m-1]公主所在。

只能向右or向下移动。

格子上的数字代表:加减血。

若到达某个格子勇士血量<1那么,勇士立即死亡。游戏失败。

求,至少在出发时,勇士的初始血量是多少。

Example 1:
Input: dungeon = [[-2,-3,3],[-5,-10,1],[10,30,-5]]
Output: 7
Explanation: The initial health of the knight must be at least 7 if he follows the optimal path: RIGHT-> RIGHT -> DOWN -> DOWN.

Example 2:
Input: dungeon = [[0]]
Output: 1
 

Constraints:
m == dungeon.length
n == dungeon[i].length
1 <= m, n <= 200
-1000 <= dungeon[i][j] <= 1000

  

解法:DP

1.状态:dp[i][j]:从[i, j]到达终点,在[i, j]至少需要的血量

  • [i, j]:当前所在坐标

2.选择:min

  • 向下走:下方格子dp[i+1][j] - 当前格子的血量消耗 dungeon[i][j]
  • 向右走:右方格子dp[i][j+1] - 当前格子的血量消耗 dungeon[i][j]

⚠️ 注意:这时如果当前坐标至少需要的血量<=0,那么会失败,因此初始化血量至 1。

3.base:

最后一个格子,减去当前格子的血量后,至少需要 1。

那么在最后一个格子之后的,下方[n-1, m] 和 右方[n, m-1] =1

代码参考:

 1 class Solution {
 2 public:
 3     //dp[i][j]: from cell[i][j] can reach cell[n][m] need at least initial blood point.
 4     //opt: min 
 5     // down:  dp[1] = dp[i+1][j]-cell[i][j]  
 6     // right:  dp[1] = dp[i][j+1]-cell[i][j]  //current blood
 7     //base:
 8     //dp[n][m-1]=1
 9     //dp[n-1][m]=1
10     int calculateMinimumHP(vector<vector<int>>& dungeon) {
11         int n=dungeon.size(), m=dungeon[0].size();
12         vector<vector<int>>dp(n+1, vector<int>(m+1, INT_MAX));
13         dp[n][m-1]=1;
14         dp[n-1][m]=1;
15         for(int i=n-1; i>=0; i--) {
16             for(int j=m-1; j>=0; j--) {
17                 int need = min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j];
18                 dp[i][j] = need<=0? 1:need;
19             }
20         }
21         return dp[0][0];
22     }
23 };
原文地址:https://www.cnblogs.com/habibah-chang/p/14607547.html