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 };