一. dp, 我自己的方法。 假设dp为每个位置最低需要的血量,初始化为1。可以反着推导dp,设置最右下角,dp[m-1][n-1] = 1;
从右下角开始推导到左上角。三种情况:
1. 就是右下角,所需最少血量1 - dungeon[i][j],如果小于0,则为1滴血就够了;
2. 如果不是最后一列,最低血量为前一格子减去当前,为dp[i][j+1] - dungeon[i][j],并和1比较;
3. 如果不是最后一行,也不是最后一列,为右边和下边最小的一个,min(dp[i][j+1], dp[i+1][j])-dungeon[i][j],也和1比较;
4. 如果不是最后一行,但是最后一列,只需要和下边比较即可。
class Solution {
public:
int calculateMinimumHP(vector>& dungeon) {
int m = dungeon.size(), n = dungeon[0].size();
vector> dp(m, vector(n,1));
dp[m-1][n-1] = 1;
for(int i=m-1;i>=0;i--) {
for(int j=n-1;j>=0;j--) {
if(i==m-1 && j==n-1) dp[i][j] = max(1, 1 - dungeon[i][j]);
if(j!=n-1) dp[i][j] = max(1, dp[i][j+1] - dungeon[i][j]);
if(i!=m-1) {
if(j!=n-1) dp[i][j] = max(1, min(dp[i][j+1], dp[i+1][j])-dungeon[i][j]);
else dp[i][j] = max(1,dp[i+1][j]-dungeon[i][j]);
}
}
}
return dp[0][0];
}
};
二. 参考其他人的,差不多思路,从右下向左上推导dp,妙的地方在于扩充dp为(n+1,m+1)大小,并赋值INT_MAX,这样省去判断。