写了半天从[0][0]开始的,代码有90多行,就过了一个样例。。看了题解,原来只能倒着来。。额额
1、题解里写得最简洁的:
https://leetcode-cn.com/problems/dungeon-game/solution/c-dp-10xing-by-pjpj/
dp[i][j]
表示从[i][j]
位置到[m-1][n-1]
需要的最小血量,即到[i,j]
时勇士的血量最少得这么多
dp[i][j] = max(1, (min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j]));
class Solution {
public:
int calculateMinimumHP(vector<vector<int>>& dungeon) {
int m = dungeon.size(), n = dungeon[0].size();
vector<vector<int>>dp(m + 1, vector<int>(n + 1, INT_MAX/10)); //初始化为无穷大
dp[m][n-1] = 1;
for(int i = m - 1; i >= 0; i--)
{
for(int j = n - 1; j >= 0; j--)
{
dp[i][j] = max(1, (min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j]));
}
}
return dp[0][0];
}
};
2、这个可能好理解点
class Solution {
public:
int calculateMinimumHP(vector<vector<int>>& dungeon) {
int m = dungeon.size(), n = dungeon[0].size();
vector<vector<int>>dp(m, vector<int>(n, 0));
//当dungeon[m-1][n-1] >= 0,这 1 - dugeon[m-1][n-1] <= 1
//反之,1 - dugeon[m-1][n-1] > 1
dp[m-1][n-1] = max(1, 1 - dungeon[m-1][n-1]);
for(int i = n-2; i >= 0; i--)
{
dp[m-1][i] = max(1, (dp[m-1][i+1] - dungeon[m-1][i]));
}
for(int i = m-2; i >= 0; i--)
{
dp[i][n-1] = max(1, (dp[i+1][n-1] - dungeon[i][n-1]));
}
for(int i = m - 2; i >= 0; i--)
{
for(int j = n - 2; j >= 0; j--)
{
dp[i][j] = max(1, (min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j]));
}
}
return dp[0][0];
}
};
3、空间优化:
class Solution {
public:
int calculateMinimumHP(vector<vector<int>>& dungeon) {
int m = dungeon.size(), n = dungeon[0].size();
vector<int>dp(n + 1, INT_MAX/10);
dp[n-1] = 1;
for(int i = m - 1; i >= 0; i--)
{
dp[n-1] = max(1, dp[n-1] - dungeon[i][n-1]);
for(int j = n - 2; j >= 0; j--)
{
dp[j] = max(1, (min(dp[j], dp[j+1]) - dungeon[i][j]));
}
}
return dp[0];
}
};