(37)174. 地下城游戏

题目链接:
https://leetcode-cn.com/problems/dungeon-game/
难度:困难
174. 地下城游戏
	一些恶魔抓住了公主(P)并将她关在了地下城的右下
角。地下城是由 M x N 个房间组成的二维网格。我们英勇
的骑士(K)最初被安置在左上角的房间里,他必须穿过地下
城并通过对抗恶魔来拯救公主。
	骑士的初始健康点数为一个正整数。如果他的健康点数
在某一时刻降至 0 或以下,他会立即死亡。
	有些房间由恶魔守卫,因此骑士在进入这些房间时会失
去健康点数(若房间里的值为负整数,则表示骑士将损失
健康点数);其他房间要么是空的(房间里的值为 0),要
么包含增加骑士健康点数的魔法球(若房间里的值为正整数,
则表示骑士将增加健康点数)。
	为了尽快到达公主,骑士决定每次只向右或向下移动一
步。
	编写一个函数来计算确保骑士能够拯救到公主所需的最
低初始健康点数。
	例如,考虑到如下布局的地下城,如果骑士遵循最佳路
径 右 -> 右 -> 下 -> 下,则骑士的初始健康点数至少为 
7。
-2 (K)	-3 	   3
-5	    -10	   1
10	     30   -5 (P)

说明:
	骑士的健康点数没有上限。
	任何房间都可能对骑士的健康点数造成威胁,也可能增
加骑士的健康点数,包括骑士进入的左上角房间以及公主被
监禁的右下角房间。

不算很难 相对于困难程度的题是有些简单了(虽然不是自己独立做出来的。。。)
有几个需要注意的点:

  1. 从右下到左上 这道题目一看就是动态规划 毫无疑问。但是从左上到右下计算很麻烦 选择从右下到左上
    (从左上到右下需要记录两个值
    1 从出发点到当前点的路径和
    2 从出发点到当前点所需的最小初始值

     路径和  最小初始值不一样 比如:
     -1    4    0
      2   -3    3
      1    4   -1 
      从(0,0)->(1,1) 路径和为0 最小初始值为2 (路径和是为了计算下一步所保存的)
    

dp[i][j] 记录从(i,j)到(m,n)的最小值
不考虑边界情况 方程为:
dp[i][j]=max(min(dp[i+1][j],dp[i][j+1])-dungeon[i][j],1)
考虑边界情况
i=n-1或j=m-1时(不同时成立) 对于min(dp[i+1][j],dp[i][j+1])可以将dp中设置为最大值 这样就会选择未越界的一个
i=n-1且j=m-1 dp[i+1][j] dp[i][j+1]均越界所以 可以设置dp[n-1][m]=dp[n][m-1]=1(当然你也可以只设置一个)

为什么是1 注意:
	骑士的初始健康点数为一个正整数。如果他的健康点
数在某一时刻降至 0 或以下,他会立即死亡。
	任何房间都可能对骑士的健康点数造成威胁,包括骑士
进入的左上角房间以及公主被监禁的右下角房间。
	必须保证勇者在经过公主房间后依然可以剩余1点生命
所以可以设置dp[n-1][m]=dp[n][m-1]=1 这样看保证在经
过(n-1,m-1)后剩余血量为1点
class Solution {
public:
    int calculateMinimumHP(vector<vector<int>>& dungeon) {
	    int n = dungeon.size();
        int m = dungeon[0].size();
        vector<vector<int>> dp(n + 1, vector<int>(m + 1, INT_MAX));
        dp[n-1][m]=dp[n][m-1]=1;
        for (int i=n-1;i>=0;i--){  
            for (int j=m-1;j>=0;j--){
                dp[i][j]=max(min(dp[i+1][j],dp[i][j+1])-dungeon[i][j],1);
            }
        }
        return dp[0][0];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值