Leetcode Dungeon Game

题意:给定一个矩阵,求从左上到右下走,只能向右或者向下,每到一个点会扣或者加一定的hp。要使得全过程hp大于0,问初始hp值最小是多少。

解法:

1、第一反应是spfa求个最短路,但是最终的总hp值不代表在路径中最低的hp值。也就是说需要将中间的状态表示出来,取最低。

2、既然需要中间状态,dfs复杂度太高,考虑用dp求解。

3、第一个dp思路,自然想到dist(i,j)表示到达(i,j)所累计的hp损耗值,dp(i,j)是到达(i,j)过程中hp的最低值。

dp[i][j] = Math.max( Math.min(dp[i-1][j], dist[i-1][j]+dungeon[i][j]) , Math.min(dp[i][j-1], dist[i][j-1]+dungeon[i][j]) );

但是这个求解有一个问题,当前dp[i][j]和dist[i][j]对当前是成立的,但是它会影响后续情况的发展,因为dp值是收到dist值的制约的。比如当前的dp[i-1][j]和dp[i][j-1]分别是-1,-3,dist[i-1][j]和dist[i][j-1]分别是2,10,dungeon[i][j]是-10,那么很明显应该选择从(i,j-1)来;但是同理没有办法证明当前的dp值选择,会不会因此导致dist值太小,后面减去一个dungeon值后就没有办法得出最优解。

4、无法得出最优解是因为后续的dungeon数值会对结果产生影响,所以就干脆反着来。

dp[i][j]表示从(i,j)到右下角所需要的最小hp值(正好卡主0,即最小为0),可以得出下面

dp[i][j] = Math.max( dp[i][j+1], dp[i+1][j] ) - dungeon[i][j];

因为是正好卡在0上的最优解,结果需要是1,所以最后结果+1

<span style="font-size:18px;">import java.util.Arrays;

public class Solution {
	public int calculateMinimumHP(int[][] dungeon) {

		int row = dungeon.length;
		int col = dungeon[0].length;

		int dp[][] = new int[row][col];
		dp[row - 1][col - 1] = Math.max(0, -dungeon[row - 1][col - 1]);

		for (int i = row - 2; i >= 0; i--) {
			dp[i][col - 1] = dp[i + 1][col - 1] - dungeon[i][col - 1];
			dp[i][col - 1] = Math.max(dp[i][col - 1], 0);
		}
		for (int j = col - 2; j >= 0; j--) {
			dp[row - 1][j] = dp[row - 1][j + 1] - dungeon[row - 1][j];
			dp[row - 1][j] = Math.max(dp[row - 1][j], 0);
		}

		for (int i = row - 2; i >= 0; i--)
			for (int j = col - 2; j >= 0; j--) {
				dp[i][j] = Math.min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j];
				dp[i][j] = Math.max(dp[i][j], 0);
			}

		return dp[0][0] + 1;
	}

	public static void main(String[] args) {
		Solution s = new Solution();
		// int[][] dungeon = { { -2, -3, 3 }, { -5, -10, 1 }, { 10, 30, -5 } };
		// int[][] dungeon = { { 0, 0, 0 }, { 1, 1, -1 } };
		int[][] dungeon = { { 1, -3, 3 }, { 0, -2, 0 }, { -3, -3, -3 } };
		System.out.println(s.calculateMinimumHP(dungeon));
	}

}</span>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值