关于LeetCode解题提升(三)

今天遇到一道DP题,记录一下思路,以免遗忘。

题目:地下城游戏

题目来源:https://leetcode-cn.com/problems/dungeon-game/

一些恶魔抓住了公主(P)并将她关在了地下城的右下角。地下城是由 M x N 个房间组成的二维网格。我们英勇的骑士(K)最初被安置在左上角的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。

骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。

有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。

为了尽快到达公主,骑士决定每次只向右或向下移动一步。

编写一个函数来计算确保骑士能够拯救到公主所需的最低初始健康点数。

例如,考虑到如下布局的地下城,如果骑士遵循最佳路径 右 -> 右 -> 下 -> 下,则骑士的初始健康点数至少为 7。

-2(k) -3 3
-5 -10 1
10 30 -5(p)

说明:

骑士的健康点数没有上限。

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

题目解释:求一个初始值,使其从k点出发,保证到p点后,该初始值为1.

看到这种题目想都不用想,DFS回溯一定超时..套路太深,所以能想到的第二种方法就是动态规划。

做动态规划,首先要保证三点:1.找到最优子解

2.列出转换方程

3.找到终止条件

然后,就轮到这道题的磨人之处了,一般的DP题目,无论从左上角递推到右下角,还是从右下角到左上角,都是一样的,不过这道题除了一个最优路径,还有一个骑士生命值,受到这两个变量的影响,两个出发点的答案是不一定相同的(Fuck),最后才发现从左上角到右下角不一定是最优解,而从右下角到左上角一定是最优解,至于为什么,因为自上而下,一般来说都选扣血少的点走嘛,但是你无法保证你骑士的最初的生命值稳定,但是从下往上走,我们可以确定最终状态的骑士的最低血量是多少,然后根据情况叠加。

设矩阵行长度为n,列长度为m,左上角为0,0,右下角为n-1,m-1 ,dp[i][j]为矩阵i,j上的最优解,既然已经知道出发点,所以我们需要使dp[n+1][m] = dp[n][m+1] = 1;(所以在建立dp数组的时候,需要将长宽定义为n+1,m+1,且必须将边围值设为无限大),这样才能定义dp[n-1][m-1]的初值,因为我们要求的是初始生命值,且假如扣的生命值小于0时,骑士的血由于不可能是负数,所以得使他保持一个1以上的生命值,因为每次都要选择扣血最少的方向,那么我们可以得到转换方程dp[i][j] = max(1,min(dp[i+1][j],dp[i][j+1]) - dungeon[i][j]);(dungeon为题目矩阵),所以我们就可以递推到dp[0][0],也就是我们所需要的初始生命值。

代码:

class Solution {
public:
    int calculateMinimumHP(vector<vector<int>>& dungeon) {
        int n = dungeon.size();
        int m = dungeon[0].size();
        if(!n&&!m) return {};
        vector<vector<int>> dp(n+1, vector<int>(m+1, INT_MAX));
        dp[n][m-1] = 1;
        dp[n-1][m] = 1;
        for(int i = n - 1 ; i >= 0 ; i--)
        for(int j = m - 1 ; j >= 0 ; j--)
            dp[i][j] = max(1,min(dp[i+1][j],dp[i][j+1]) - dungeon[i][j]);

        return dp[0][0];

    }
};

总结:熟悉动归结构,确定三个条件。

原文地址:https://www.cnblogs.com/xiangqi/p/12608048.html

时间: 2024-10-04 06:49:06

关于LeetCode解题提升(三)的相关文章

关于LeetCode解题提升(二)

今天遇到一道题,不得不说,思路决定一切,分享一下我的解题心路历程和对大佬的解题方式的解析与感想. 820. 单词的压缩编码 题目来源:https://leetcode-cn.com/problems/short-encoding-of-words/ 给定一个单词列表,我们将这个列表编码成一个索引字符串 S 与一个索引列表 A. 例如,如果这个列表是 ["time", "me", "bell"],我们就可以将其表示为 S = "time#

leetCode解题报告5道题(九)

题目一:Combinations Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. For example,If n = 4 and k = 2, a solution is: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ] 分析: 题意给我们一个数字n, 和一个数字k,让我们求出从 1~~n中取出k个数所能得到的组合数 所

leetCode解题报告5道题(十一)

题目一:Subsets Given a set of distinct integers, S, return all possible subsets. Note: Elements in a subset must be in non-descending order. The solution set must not contain duplicate subsets. For example, If S = [1,2,3], a solution is: [ [3], [1], [2]

leetCode解题报告5道题(六)

题目一: Longest Substring Without Repeating Characters Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the

leetCode解题报告5道题(八)

题目一: Populating Next Right Pointers in Each Node Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *next; } Populate each next pointer to point to its next right node. If there is no next right node, the

leetCode解题报告5道题(十)

Disk Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2368    Accepted Submission(s): 333 Problem Description 有很多从磁盘读取数据的需求,包括顺序读取.随机读取.为了提高效率,需要人为安排磁盘读取.然而,在现实中,这种做法很复杂.我们考虑一个相对简单的场景.磁

新建一个索引能够同时提升三条SQL的查询性能

如题 CREATE TABLE `score` (   `id` int(11) NOT NULL,   `studentid` int(11) NOT NULL,   `subjectid` int(11) NOT NULL,   `score` int(11) NOT NULL,   PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- 新建一个索引能够同时提升三条SQL的查询性能 ALTER TABLE `score` AD

LeetCode解题源代码链接集锦二

15.Sort List--链表在O(nlogn),常数空间内完成排序 关键点:中间分裂链表,采用双指针归并排序     中间分裂链表的方法:快慢指针,快指针走两步,这样就可以找到中间的了 C++:http://blog.csdn.net/jiadebin890724/article/details/21334059 Java:http://blog.csdn.net/worldwindjp/article/details/18986737 LeetCode解题源代码链接集锦二,布布扣,bubu

LeetCode解题报告:LRU Cache

LRU Cache Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set. get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise retu