原题
174.地下城游戏
2020年7月12日 每日一题
原题
方法一 动态规划
建立一个和原矩阵维度相同的矩阵,用于表示进入每一个格子之前应该至少有的生命值才能保证在之后到达最后一个格子之后生命力至少为1。
本思路java代码示例:
/*
@v7fgg
执行用时:2 ms, 在所有 Java 提交中击败了96.34%的用户
内存消耗:39.3 MB, 在所有 Java 提交中击败了100.00%的用户
2020年7月12日 18:19
*/
class Solution {
public int calculateMinimumHP(int[][] dungeon) {
int m=dungeon.length;
int n=dungeon[0].length;
//矩阵表示进入ij的时候,生命值的最小值
//对于每一个格子,进入之前既要满足进入之后不会减到小于1,又要保证在后边都不小于1,因此要反着推
int ans[][]=new int[m][n];
ans[m-1][n-1]=1-Math.min(0,dungeon[m-1][n-1]);//初始化最后一个格子,便于反推回去
//先考虑最右边竖列
for(int i=m-2;i>=0;i--){
if(dungeon[i][n-1]>=0){
if(ans[i+1][n-1]-dungeon[i][n-1]>=1){ans[i][n-1]=ans[i+1][n-1]-dungeon[i][n-1];}
else{ans[i][n-1]=1;}
}
else{ans[i][n-1]=ans[i+1][n-1]-dungeon[i][n-1];}
}
//在考虑最下边一行
for(int j=n-2;j>=0;j--){
if(dungeon[m-1][j]>=0){
if(ans[m-1][j+1]-dungeon[m-1][j]>=1){ans[m-1][j]=ans[m-1][j+1]-dungeon[m-1][j];}
else{ans[m-1][j]=1;}
}
else{ans[m-1][j]=ans[m-1][j+1]-dungeon[m-1][j];}
}
//考虑内部的元素
for(int i=m-2;i>=0;i--){
for(int j=n-2;j>=0;j--){
if(dungeon[i][j]>=0){
ans[i][j]=Math.max(1,Math.min(ans[i+1][j],ans[i][j+1])-dungeon[i][j]);
}
else{ans[i][j]=Math.min(ans[i+1][j],ans[i][j+1])-dungeon[i][j];}
}
}
return ans[0][0];
}
}
以上代码简化版:
class Solution {
public int calculateMinimumHP(int[][] dungeon) {
int m=dungeon.length;
int n=dungeon[0].length;
//矩阵表示进入ij之前,生命值的最小值
//对于每一个格子,进入之前既要满足进入之后不会减到小于1,又要保证在后边都不小于1,因此要反着推
int ans[][]=new int[m][n];
ans[m-1][n-1]=1-Math.min(0,dungeon[m-1][n-1]);//初始化最后一个格子,便于反推回去
//先考虑最右边竖列
for(int i=m-2;i>=0;i--){
ans[i][n-1]=Math.max(1,ans[i+1][n-1]-dungeon[i][n-1]);
}
//在考虑最下边一行
for(int j=n-2;j>=0;j--){
ans[m-1][j]=Math.max(1,ans[m-1][j+1]-dungeon[m-1][j]);
}
//考虑内部的元素
for(int i=m-2;i>=0;i--){
for(int j=n-2;j>=0;j--){
ans[i][j]=Math.max(1,Math.min(ans[i+1][j],ans[i][j+1])-dungeon[i][j]);
}
}
return ans[0][0];
}
}