算法地下城与勇士
Posted zhangmora
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法地下城与勇士相关的知识,希望对你有一定的参考价值。
题目
-2 (K) | -3 | 3 |
-5 | -10 | 1 |
10 | 30 | -5 (P) |
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/dungeon-game
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题
看到这种求全局最值+状态转移的题目,就想到了动态规划。
给出的数组为dungeon,我自设的数组为dp保存每个位置的最低可存活健康值。
一开始想到了从起点开始动态规划,类似贪心算法求最优路径,举个栗子:
dp[0][0]时的最低健康值为3(因为任何时候不可降至0及以下,至少为3才能在-2后仍大于0);
dp[1][0],只能从上侧来,因此dp[0][0]-dungeon[1][0]=3-(-5)=8(在这个格子的时候至少为8,才能经得住-5这样的消耗,且保证上个格子的时候也是活着的);
dp[2][0]时,只能从上侧来,因此为8-10=-2小于0了,该格子可提供的健康值大于上一步时的最低可存活健康值了,如果dp[2][0]=dp[1][0],那么如果后续格子有需要大量消耗的话,明明前面提供的健康值能补充上使用,可是dp[2][0]=dp[1][0]+dungeon[2][0]的话,后面的格子如果都没有消耗了,那么dp[2][0]就没有加上这么多健康值,这个问题就是无后效性问题,没办法预见后面的情况。
像这种前面的决策会影响到后面的情况,就可以使用从后往前的办法动态规划。
1 public int calculateMinimumHP(int[][] dungeon) { 2 int row=dungeon.length; 3 int col=dungeon[0].length; 4 //这个数组表示在i,j位置骑士需要的最小生命值 5 int[][] dp=new int[row][col]; 6 for(int i=row-1;i>=0;i--){ 7 for(int j=col-1;j>=0;j--){ 8 if(i==row-1&&j==col-1){ //终点的情况 9 dp[i][j]=Math.max(1, 1-dungeon[i][j]); 10 }else if(i==row-1){ //最后一行的情况 11 dp[i][j]=Math.max(1, dp[i][j+1]-dungeon[i][j]); 12 }else if(j==col-1){ //最后一列的情况 13 dp[i][j]=Math.max(1, dp[i+1][j]-dungeon[i][j]); 14 }else{ 15 dp[i][j]=Math.max(1, Math.min(dp[i+1][j],dp[i][j+1])-dungeon[i][j]); 16 } 17 } 18 } 19 return dp[0][0]; 20 }
解释一下几个式子:
在终点时:
dp[i][j]=Math.max(1, 1-dungeon[i][j]);如果dungeon>1,说明终点位置能提供给骑士健康值让骑士,那么刚到这个位置时骑士保证自己活着就行了,dp为1;如果dungeon=0或<0,则终点不能提供给骑士生命,甚至还要消耗生命,那么骑士不仅要活着到这个位置,还要经得住在这个位置上的消耗,则为1-dungeon,例如dungeon为-9的话那么骑士的健康值至少为10.
最后一行和最后一列:
最后一行时骑士只能从右边走过来,骑士保存着上一步(从终点方向来的)的健康值,
①如果当前位置为负,则dp[i][j]=dp[i][j+1]-dungeon[i][j],也就是准备上将要被耗掉的健康值才能保证骑士活着,
②如果当前位置为0,则dp[i][j+1]-dungeon[i][j]=dp[i][j+1],骑士保持上一步的健康值就能活,
③如果当前位置为正,说明当前位置能提供给骑士健康值,dp[i][j+1]-dungeon[i][j]>=1时当前位置虽然能提供一些但是不能提供所有dp[i][j+1]需要的,dp[i][j+1]-dungeon[i][j]<1时当前位置能提供所有所需的健康值,即dp[i][j+1]需要的可以完全从dp[i][j]获取,骑士只需要准备1的健康值让自己活着就好,之后再到终点都不必担心。最后一列时骑士只能从下面走过来,情况类似。
其它一般情况:
每个位置都可以从右边和下边走来,因此比较右边和下边位置的dp值取最小的路走,减去dungeon,若大于1说明当前位置要消耗健康值或者能提供少量健康值,若小于1说明当前位置能提供非常多的健康值则取1即可。
以上是关于算法地下城与勇士的主要内容,如果未能解决你的问题,请参考以下文章
易语言隐藏显示 怎么显示?版本 2 窗口隐藏显示 (取句柄 (“DNF.EXE”, , “地下城与勇士”))