题目
分析过程
1.这道题还是要用到动态规划,但是与之前的有些不同,如果从最大收益正向考虑时,会产生三个储存时间,而且不是简单的在最后加一个判断条件,勇士在中间也必须保持正血量,因此行不通,就算实现了,时间复杂度也过高。
2.采用倒推的方法,根据题意要救出公主,从公主的位置出发,若公主当前位置为正,则勇士健康值最少为1,若为负,则需要上一步dp-当前格数值
3.用dp[i][j] 表示从坐标 (i,j) 到终点所需的最小初始值,在一般情况下,我们只需要关注向右和向上这两者健康点最小值
给出动态规划方程
dp[i][j]=max(min(dp[i+1][j],dp[i][j+1])−dungeon(i,j),1)
代码
func calculateMinimumHP(dungeon [][]int) int {
n := len(dungeon)
m := len(dungeon[0]) //读取网格数
dp := make([][]int, n) //创建动态存储空间,即勇士健康点
for i := 0; i < n; i++ {
dp[i] = make([]int, m)
}
if dungeon[n-1][m-1] > 0 {
dp[n-1][m-1] = 1//判断最后一格即公主所在格数的上面和左边两格数值是否大于0,若是则勇士健康点为1
} else {
dp[n-1][m-1] = 1 - dungeon[n-1][m-1] //不是,则上一步dp-当前格数值
}
for i := n - 1; i >= 0; i-- {
for j := m - 1; j >= 0; j-- {
if i == n-1 && j == m-1 {
continue //判断健康点是否大于0,不是则死亡
} else if j == m-1 {
dp[i][j]=Max(1,(dp[i+1][j]-dungeon[i][j]))
} else if i == n-1 {
dp[i][j]=Max(1, (dp[i][j+1]-dungeon[i][j]))
}else {
t1 :=Max(1,dp[i+1][j]-dungeon[i][j])
t2 :=Max(1,dp[i][j+1]-dungeon[i][j])
dp[i][j]=Min(t1,t2)
} //两次循环判断一般情况,获得最小值
}
}
return dp[0][0]
}
func Min(x, y int) int {
if x < y {
return x
}
return y
}
func Max(x, y int) int {
if x > y {
return x
}
return y
}