174地下城游戏——力扣算法系列2020.07.12 Python

第18天
2020.07.12 周日
难度系数:困难
题目:174地下城游戏
一些恶魔抓住了公主(P)并将她关在了地下城的右下角。地下城是由 M x N 个房间组成的二维网格。我们英勇的骑士(K)最初被安置在左上角的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。
骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。
有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。
为了尽快到达公主,骑士决定每次只向右或向下移动一步。
编写一个函数来计算确保骑士能够拯救到公主所需的最低初始健康点数。

例如,考虑到如下布局的地下城,如果骑士遵循最佳路径 右 -> 右 -> 下 -> 下,则骑士的初始健康点数至少为 7。
-2 (K)	-3	  3
-5	   -10	  1
10	    30 	-5 (P)

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/dungeon-game
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
——————————我是分割线——————————
解法:
思路:动态规划 从右下到右上
这题和 2020.07.06 63不同路径 很像
状态定义:
dp[i][j]:从坐标(i,j)到终点所需的最小初始值
对于dp[i][j]只关心dp[i][j+1]dp[i+1][j]的最小值即可。记当前格子值为dungeon(i,j),则坐标(i,j)初始值只需要达到min_res-dungeon(i,j)即可,且初始值需要大于等于1。
状态转移方程:
dp[i][j] = max(min(dp[i][j+1],dp[i+1][j])-dungeon(i,j) , 1)
最后返回左上格子的值dp[0][0]即可。

代码:

# leetcode174地下城游戏 2020.07.12
class Solution(object):
    def calculateMinimumHP(self, dungeon):
        """
        :type dungeon: List[List[int]]
        :rtype: int
        """
        hang = len(dungeon) #矩阵行
        lie = len(dungeon[0]) #矩阵列
        BIG = 10**9 #每格默认无穷大
        dp = [[BIG]*(lie+1) for i in range(hang+1)] #新矩阵 多一行一列是为了给边界赋值
        dp[hang][lie-1] = dp[hang-1][lie] = 1 #右下角下方和右方格子赋值为1 
        # 因为要取两个格子的min 然后该格值为min-原矩阵中该格值和1中的最大值

        for i in range(hang-1,-1,-1): #从下到上 遍历行
            for j in range(lie-1,-1,-1): #从右到左 遍历列
                min_res = min(dp[i+1][j],dp[i][j+1]) #取右和下两个格子的最小
                dp[i][j] = max(min_res-dungeon[i][j] , 1) #该格值
        return dp[0][0] #返回左上 即初始血量
dungeon = [
            [0,-2,3],
            [-1,0,0],
            [-3,-3,-2]
            ]
print(Solution().calculateMinimumHP(dungeon))
# 3

174地下城游戏——力扣算法系列2020.07.12 Python_第1张图片

以上面代码中的例子来写下过程:
从左到右,从下到上遍历
174地下城游戏——力扣算法系列2020.07.12 Python_第2张图片

第一步:(2,2)
min_res = min(dp[2][3],dp[3][2]) = 1
dp[2][2] = max(min_res-dungeon(2,2) , 1) = 3
174地下城游戏——力扣算法系列2020.07.12 Python_第3张图片
————————————————————
第二步:(2,1)
min_res = min(dp[2][2],dp[3][1]) = 3
dp[2][1] = max(min_res-dungeon(2,1) , 1) = 6
174地下城游戏——力扣算法系列2020.07.12 Python_第4张图片
————————————————————
第三步:(2,0)
min_res = min(dp[2][1],dp[3][0]) = 6
dp[2][0] = max(min_res-dungeon(2,0) , 1) = 9
174地下城游戏——力扣算法系列2020.07.12 Python_第5张图片
————————————————————
第四步:(1,2)
min_res = min(dp[1][3],dp[2][2]) = 3
dp[1][2] = max(min_res-dungeon(1,2) , 1) = 3
174地下城游戏——力扣算法系列2020.07.12 Python_第6张图片
————————————————————
第五步:(1,1)
min_res = min(dp[1][2],dp[2][1]) = 3
dp[1][1] = max(min_res-dungeon(1,1) , 1) = 3
174地下城游戏——力扣算法系列2020.07.12 Python_第7张图片
————————————————————
第六步:(1,0)
min_res = min(dp[1][1],dp[2][0]) = 3
dp[1][0] = max(min_res-dungeon(1,0) , 1) = 4
174地下城游戏——力扣算法系列2020.07.12 Python_第8张图片
————————————————————
第七步:(0,2)
min_res = min(dp[0][3],dp[1][2]) = 3
dp[0][2] = max(min_res-dungeon(0,2) , 1) = 1
174地下城游戏——力扣算法系列2020.07.12 Python_第9张图片
————————————————————
第八步:(0,1)
min_res = min(dp[0][2],dp[1][1]) = 1
dp[0][1] = max(min_res-dungeon(0,1) , 1) = 3
174地下城游戏——力扣算法系列2020.07.12 Python_第10张图片
————————————————————
第九步:(0,0)
min_res = min(dp[0][1],dp[1][0]) =
dp[0][0] = max(min_res-dungeon(0,0) , 1) = 3
174地下城游戏——力扣算法系列2020.07.12 Python_第11张图片
————————————————————
返回dp[0][0] = 3

你可能感兴趣的:(174地下城游戏——力扣算法系列2020.07.12 Python)