题目:给定一二维数组map,含义是一张地图。骑士只能从左上角出发,向下或向右最后到达右下角见到公主。地图中的负数代表此处有怪兽,会让骑士损失血量;地图中的正数代表此处有血瓶,能让骑士回血。要求骑士从左上角到右下角的任何位置,血量都不能少于1。问为了保证能够见到公主,骑士的初始血量是多少?
实现:动态规划,生成和地图大小一样的dp动态规划矩阵。dp[i][j]表示要到达map[i][j]前应该有的最小血量。
第一种分析方法:
- dp[i][j+1]表示选择向右走最终到达右下角的血量要求,则在当前(i,j)位置加完血或扣完血血量等于dp[i][j+1]即可,即dp[i][j]=dp[i][j+1]]-map[i][j];同时要保证骑士血量至少为1,则向右走的要求为dp[i][j]=max{dp[i][j+1]]-map[i][j],1}.
- dp[i+1][j]表示选择向下走最终到达右下角的血量要求,则在当前(i,j)加完血或扣完血血量等于dp[i+1][j]即可。后面分析与步骤1相同。dp[i][j]=max{dp[i+1][j]]-map[i][j],1}
- 为了选择最优的路径,dp[i][j]=min{max{dp[i][j+1]]-map[i][j],1},max{dp[i+1][j]]-map[i][j],1}}
- 从上面几步可以看出,当前的值依靠下面和右边位置的值,因此计算dp矩阵是从右下角开始,从右至左、从下往上进行计算。dp[0][0]就是需要的初始血量。
第二种分析方法:这样是比较好理解,但是上面的分析方法更容易计算dp[i][j]。
有两个方向可以到达dp[i][j]:
- 从上边下来,则dp[i-1][j]需要保证的血量为dp[i-1][j]=dp[i][j]-map[[i-1][j]。同时为了保证最小血量为1的要求,则dp[i-1][j]=max{dp[i][j]-map[[i-1][j],1}。
- 从左边过来,则dp[i][j-1]=max{dp[i][j]-map[[i][j-1],1}。
1 | public class KnightAndPrincess { |
输出:
1 | dp动态规划矩阵: |