![](https://img-blog.csdnimg.cn/20201014180756928.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
动态规划
文章平均质量分 67
动态规划
辰阳星宇
这个作者很懒,什么都没留下…
展开
-
198、【动态规划】leetcode ——983. 最低票价:记忆化搜索(C++版本)
(1)dp[i]含义: 第i天时,所需要的最低消费。(2)递推公式: dp[i]=min(dp[i−1]+cost[0],dp[i−7]+cost[1],dp[i−30]+cost[2])dp[i] = min(dp[i - 1] + cost[0], dp[i - 7] + cost[1], dp[i - 30] + cost[2])dp[i]=min(dp[i−1]+cost[0],dp[i−7]+cost[1],dp[i−30]+cost[2]),从上述三种情况中反推出来那种情况到达第i天时开销最小。原创 2023-03-11 22:19:51 · 296 阅读 · 0 评论 -
197、【动态规划】AcWing —— 901. 滑雪(C++版本)
整体思路就是依次进行递归遍历,从不同的起始位置出发找到一条最长区域路径。每次探寻时,从上下左右四个方向寻找,最终找到一条最长路径。,意为在已有的结果中和向上下左右某一个方向继续探索后,找到一个最大区域长度结果。dp[i][j] = 1,每个自身代表一个长度。位于(i, j)时,具有的最长区域路径长度。原创 2023-03-11 11:38:08 · 535 阅读 · 0 评论 -
196、【动态规划】AcWing —— 285. 没有上司的舞会(C++版本)
题目是要构造一个树形关系,在选择时,有直接上下级关系的不能选,但是对于有间接上下级关系的和非上下级关系的都可以选。dp[i][0]:不选节点i时,具有的最大快乐数。dp[i][1]:选节点i时,具有的最大快乐数。dp[i][1] = happy[i],当选择孩子节点时,初始时候为自身的快乐数值。,意为在不选择i节点的情况下,选择孩子节点和不选择孩子节点时候找到一个最大值。(其中j为i的孩子节点),意为选择当前节点的情况下加上不选择孩子节点的情况;后序遍历,从左到右,从下到上,将低层结果传递给上一层。原创 2023-03-10 21:49:37 · 417 阅读 · 1 评论 -
195、【动态规划】AcWing —— 91. 最短Hamilton路径(C++版本)
到达点j并且状态为i时,具有的最短路径长度,其中状态j用状态压缩二进制的方式表示。j中从0-n-1位分别对应点0到点n-1,j中某一位的值为1时代表走入此点,值为0时代表不走入此点。因为要求的最短路径需要在之前的点已经添加的基础上进行更新,先遍历状态再遍历点,可以得知在状态i(某些点添加某些点未添加)时,点j到达起始点0的最短路径。dp[1][0] = 0,表示走入初始点0时,此时的距离出发点的距离为0。加减法的优先级 > 位运算的优先级,需要对位元算带括号。)时,从第k个点到达第j个点所需要的路径长度。原创 2023-03-09 11:27:05 · 449 阅读 · 0 评论 -
194、【动态规划】AcWing —— 291. 蒙德里安的梦想:状压dp详细解析(C++版本)
答:因为我们要求的是从第j-1列转化到第j列是的所有合法状态,因此先for循环j时,代表我们的目标列j此时的状态,此时第j列的空格数不为偶数个,而是奇数个,就会导致1×2的长方体一定不能填充满这一列,因此此状体不合法。,代表从当前位置横着新摆放一个长方体(此时第j+1列、第i行,会由第i列伸出一个长方体)。此时由于第j-1列新横放的方块和第j列新横放的方块出现重叠,因此此状态不合法。,表示从第i-1列到达第i列,可转化为状态j的所有合法状态求和。第i列处,状态为j时,合法的方案数。因此,本问题就转化为了,原创 2023-03-08 12:31:32 · 628 阅读 · 2 评论 -
192、【动态规划】leetcode ——64. 最小路径和:回溯法+动态规划(C++版本)
分别向右或下进行探查此方式会超时。原创 2023-03-05 21:02:26 · 393 阅读 · 1 评论 -
191、【动态规划】AcWing —— 900. 整数划分:完全背包解法+加减1解法(C++版本)
例如:组合成3的方案可以为2、1和1、1、1,当我们想要得到组合成4的方案,那么就可以分别从2、1和1、1、1演化过来,就是2、1、1和1、1、1、1,此时3中这一部分含有最小值为1的方案个数与4中这一部分含有最小值为1的方案个数其实是相同的。例如:组合成3的方案可以为2、1和1、1、1,当我们想要得到组合成4的方案,那么就可以分别从2、1和1、1、1演化过来,就是2、1、1和1、1、1、1,此时3中这一部分含有最小值为1的方案个数与4中这一部分含有最小值为1的方案个数其实是相同的。从左到右,从上到下。原创 2023-03-05 12:37:25 · 435 阅读 · 0 评论 -
190、【动态规划】AcWing ——282. 石子合并(C++版本)
其中(i < k < j),k为区间的分割点,x为下标i到j之间的总代价和。因为题中要求的就是每次加上合并后的结果,因此加上这段区间之和。dp[i][j] = MAX(i ≠ j),因为求最小值,所以让其取最大。dp[i][i] = 0,区间长度为1时,结果为0.从上至下,从左至右,区间长度有小到大一个一个遍历。进而得出整个大区间上最优解的dp算法。从下标i到下标j之间,最小的代价和。,求解一段区间上的最优解。原创 2023-03-04 11:34:26 · 508 阅读 · 0 评论 -
189、【动态规划】leetcode ——312. 戳气球(C++版本)
原题链接:312. 戳气球很多求最值实际上就是穷举所有情况,对比找出最值。因为不同的戳气球顺序会产生不一样的结果,所以实际上这就是一个全排列问题。此方式会超时此题和其他动态规划题的一个区别就是,、、相互有关,而动态规划算法使用的一个重要条件就是子问题需要相互独立。因此,为了可以使用动态规划,需要巧妙地定义数组,避免子问题产生相关性。因为,戳到最后时,也会左右乘上1,因此我们让的前后都加上1。(1)dp[i][j]含义:在到中可得到的最大硬币数(因为首尾新增了两个数,因此不戳首尾按开区间算)。(2)递推公原创 2023-03-03 11:02:28 · 443 阅读 · 0 评论 -
【算法刷题】动态规划算法题型及方法归纳
动态规划中每一个状态一定是由上一个出来,根据这个特点,可以在过程中,存储某一条件下的数据,当再次遍历该条件时,直接取该条件对应的数据即可,可以避免重复计算,减少时间。原创 2023-02-25 22:01:30 · 1948 阅读 · 0 评论 -
183、【动态规划】leetcode ——516. 最长回文子序列(C++版本)
时,则尝试排除左端或右端元素,找到可以构成回文子序列的最大长度。从下标i到下标j之间,s具有的最大回文子序列长度。dp[i][i]=1,自身为最小回文串,其余为0。基础上,再加上这个两个相等的数,变为。两个状态,两个操作。从下到上,从左至右。原创 2023-02-25 21:55:38 · 253 阅读 · 0 评论 -
182、【动态规划/数组】leetcode ——647. 回文子串:动态规划+双指针(C++/Python版本)
判定是否为回文串。当子串为奇数长度时,回文串中心唯一;当子串为偶数长度时,会由两个数作为回文串中心。如此时子串长度超过2时,则需要根据上一次i与j之间的位置结果进行判定,若。dp[i][j] = false,都为进行判定时,为false。因为每次子串为从两边向中间伸缩,因此为从下至上,从左至右。bool类型变量,s中下标i到下标j之间是否为回文串。,则再加上当前的情况一定为回文串,执行。时,若此时子串的长度为1或2时(),此时一定为回文串,执行。动态规划的思路是每次判定。两个状态,三种操作。原创 2023-02-25 17:00:52 · 302 阅读 · 0 评论 -
181、【动态规划】leetcode ——72. 编辑距离(C++版本)
dp[i][0] = dp[0][i] = i,另一方为0时需要删除i次或修改i次。dp中的i对应word1中的i-1,dp中的j对应word2中的j-1。,直接由上一步转移过来。结尾子串,经过最少次增删改后,可让。从左到右,从上到下。原创 2023-02-24 21:22:51 · 461 阅读 · 1 评论 -
180、【动态规划】leetcode ——583. 两个字符串的删除操作:两种动态规划思路(C++版本)
的区别在于,1143中求的是两个序列中的最长公共子序列,而本题是要找到最少删除多少个元素后可以得到公共子序列。实际上,如果要找到删除元素最少,也就是要找到一个最长公共子序列,然后用两个序列的之和减去最长公共子序列长度的二倍,即可得到最少删除的元素个数。,分别试着删除一个和两个,由于前方删除一个的情况都已经含义删除两个时加上二的情况,所以只用写。以word1[i - 1]和word2[j - 1]为结尾的字符串,最少删除元素的个数。中相当于是只能删除一个字符串中的元素,而本题是两个字符串中的元素都可以删除。原创 2023-02-24 11:30:25 · 354 阅读 · 0 评论 -
179、【动态规划】leetcode ——115. 不同的子序列(C++版本)
相等时,可来源于s和t末尾对应的dp状态。由于要得到的是累积的个数,因此需要再加上保持目标串t不变,选择串s向前缩一位对应的dp状态。都不等时,保持目标串t的不变,选择串s向前缩一位的状态直接复制给不等的情况。dp[i][0] = 1,意为选择为空的时候,仅有一种情况(选择串中也什么都不选),dp[0][i] = 0,其中dp[0][0] = 1。的区别在于,选择串中可能会有多个目标串满足,因此要对满足目标串的进行累积计算。为结尾,字符串t为字符串s的子串个数。从左到右,从上到下。原创 2023-02-24 10:22:08 · 120 阅读 · 0 评论 -
178、【数组/动态规划】leetcode ——392. 判断子序列:双指针+动态规划(C++版本)
的时候,因为要求字符串s为t的子串,因此固定s末尾指向位置不动,让指向t的指针向前面移动一个,由此位置转移状态,即。由此方式,遍历完整个字符串。的时候,从上一个状态转移过来,的过程中,每遇到一个。指向元素相等时,则让。原创 2023-02-23 17:43:34 · 105 阅读 · 0 评论 -
177、【动态规划】leetcode ——11035. 不相交的线(C++版本)
问题转化:如果想要不相交的连接两两相同的数字,那么就要求按从左到右的顺序,递增找公共子序列。这样子问题就转化为了找到两个最长公共子序列。原创 2023-02-23 13:14:10 · 131 阅读 · 0 评论 -
176、【动态规划】leetcode ——1143. 最长公共子序列(C++版本)
因为i-1和j-1时不等,则取取消一个末尾后,二者中的继承的最大长度值。text2[j - 1]`结尾,具有的最长公共子序列。的区别在于此时不要求令一个数组中元素连续。,在上一个长度的基础上加一。以text1[i - 1]原创 2023-02-22 21:11:10 · 335 阅读 · 0 评论 -
175、【动态规划】leetcode ——718. 最长重复子数组 (C++版本)
dp[i][0] = dp[0][i] = 0,因为以i-1和j-1为结尾,故此时为无意义,因此设为0便于后续计算。结尾所具有的最长重复子数组长度。(以i-1而不以i为结尾的目的是可以简化代码),满足两者在i和j处相等时,就以。的基础上再加一个长度。原创 2023-02-22 19:28:39 · 99 阅读 · 0 评论 -
174、【动态规划/贪心算法/滑动窗口】leetcode ——674. 最长连续递增序列:一题多解 (C++版本)
dp[i] = dp[i - 1] + 1,每遇到一个连续的字符,就在上一个已有的最长子序列长度上加一。dp[i] = 1,自身最少为一个。从下标i往前的最长连续子序列长度。原创 2023-02-21 21:33:43 · 127 阅读 · 0 评论 -
173、【动态规划】leetcode ——300. 最长递增子序列 (C++版本)
从之前已有结果,和现在发现情况找到一个最大值。因位找到是递增序列,那么若j-i为递增序列,则i在比。外层从小到大遍历,内从每次从0位置开始遍历更新,每遍历到。外层只能从小到大,内层从小到大或从大到小都可以。dp[i] = 1,因为最少为自身一个。下标0-i之间,最大子序列长度。下标元素大时,一定也会比。原创 2023-02-21 17:03:19 · 152 阅读 · 0 评论 -
172、【动态规划】leetcode ——714. 买卖股票的最佳时机含手续费 (C++版本)
因为会有扣除手续费,可能会导致卖出去后扣得费用更多所以返回这两个中的最大值。的区别在于含有一个收费,只需要在最后卖出时候扣除手续费后再比较即可。,也就是上一次没有卖的时候和这次进行买卖后比较出最大值。注意:最后返回的可以不为。原创 2023-02-20 18:49:53 · 94 阅读 · 0 评论 -
171、【动态规划】leetcode ——309. 最佳买卖股票时机含冷冻期 (C++版本)
dp[0][0] = -prices[0],因为不能当天买当天卖dp[0][1] = dp[0][2] = dp[0][3]为非法变量,为了便于后续计算,由后续的需求可反推知,应把这三个初始化为0。:取三种操作的最大值。第二种,昨天不持有并且昨天不为冷冻期,今天买入股票。第一种,之前已不持有且昨天不为冷冻期,保持。第二种,之前已不持有并且昨天为冷冻期,从冷冻期转移过来。:今天不持有股票并且明天不为冷冻期时,最大收益。:持有股票时的最大收益,在之前的就已持有的状态和从非冷冻期后当天买入的状态中,去最大值。原创 2023-02-20 18:27:00 · 772 阅读 · 0 评论 -
170、【动态规划】leetcode ——188. 买卖股票的最佳时机 IV:二维数组+一维数组 (C++版本)
dp[i][2 * k - 1] = 第i天第k次已持有股票时的最大总收益 = max(第i-1天第k次已持有股票时的最大总收益,第i天第k次已持有股票时的最大总收益(第i-1天第k - 1次不持有股票时的最大总收益 - prices[i]))dp[i][2 * k] = 第i天第k次已不持有股票时的最大总收益 = max(第i-1天第k次已不持有股票时的最大总收益,第i天第k次已不持有股票时的最大总收益(第i-1天第k次已持有股票时的最大总收益 + prices[i]))但处理逻辑还是与之前相同。原创 2023-02-18 20:40:48 · 150 阅读 · 0 评论 -
169、【动态规划】leetcode ——123. 买卖股票的最佳时机 III:二维数组+一维数组 (C++版本)
dp[i][3] = max(dp[i - 1][3], dp[i][2] + prices[i]),表示在之前已第二次不持有股票和第i天第二次持有股票中,找一个最大值,作为最大收益。dp[i][2] = max(dp[i - 1][2], dp[i][1] + prices[i]),表示在之前已第一次不持有股票和第i天把股票售出后中,找一个最大值,作为最大收益。,每次到第i次遍历时,max中的dp[1]就相当于是第i-1次时计算得到的结果,取完最大值后,dp[1]就变为了dp[i][1]原创 2023-02-18 13:55:13 · 463 阅读 · 0 评论 -
130、【贪心算法/动态规划】leetcode ——122. 买卖股票的最佳时机 II(C++版本)
贪心策略:获取所有的上升坡度,每个上升坡度的和是局部最优解。全局最优解:总利润最大,而每个上升坡度的和就是最大利润。的情况,为正数数的差值,为负数时不记录,也就是记录为0。用来记录购买时的金额,用来记录卖出时的金额,用来记录当前总利润。原创 2023-02-01 12:00:56 · 222 阅读 · 0 评论 -
168、【动态规划】leetcode ——121. 买卖股票的最佳时机:dp数组+变量优化 (C++版本)
dp[i][1] = max(dp[i - 1][1], prices[i] - dp[i - 1][0]),由于是不持有股票,因此也会有两种情况。一种是之前不持有时的收益情况(可能已经进行过一次买卖交易,也可能一直没有买入过),另一种是现在将已有股票售出,就用当前卖出的价格减去之前最小买入的价格。dp[i][0] = min(dp[i - 1][0], prices[i]),由于是持有股票,因此可能会有两种情况。dp[0][0] = -prices[0],刚开始买入第一天买入的情况。原创 2023-02-17 13:08:10 · 161 阅读 · 0 评论 -
165、【动态规划】leetcode ——337. 打家劫舍 III:记忆化递归+动态规划(C++版本)
因为dp数组是从小到大,大的要基于小的结果去进行操作。所以,需要使用后序遍历的方式,左右中的顺序遍历。底层的结果返回给上一层,上一层处理完后再返回给其上一层。对左右遍历完后,用val1记录不偷时的情况,找出偷下一个结点值更大,还是不偷下一个结点值更大。用val2记录偷时的情况,当前结点加上不偷下一个结点时的情况。,返回值为长度为2的dp数组,下标0表示不偷root的结果,下标1表示偷root的结果。当遍历到该节点时,判定之前是否遍历过,如果遍历过,直接返回。最终,找到二者之间的最大值,返回。原创 2023-02-16 20:15:04 · 308 阅读 · 0 评论 -
166、【动态规划】AcWing ——9. 分组背包问题(C++版本)
分组背包问题是在01背包的基础上,多了一个组的概念。有若干个组,每组里面有若干个物品,每个物品只能选择一次,找到在背包容量为j的前提下,从0-i组中选择物品,达到背包里价值最大。原创 2023-02-16 17:38:58 · 145 阅读 · 0 评论 -
【动态规划】背包问题题型及方法归纳
背包问题是在规定背包容量为j的前提下,每个物品对应的体积为v[i],价值为w[i],从物品0到物品i中选择物品放入背包中,。原创 2023-02-16 15:31:16 · 5448 阅读 · 1 评论 -
164、【动态规划】leetcode ——213. 打家劫舍 II:环形列表线性化(C++版本)
可以发现,情况二和三会包含情况一,因此我们只需分别求情况二和情况三,得到的最大情况,然后再对二者取最大值,即可。的区别在于,此次的要求为环形列表,而198里的是线性链表。例如,对nums = [1,2,3,4,1]是将环形进行线性化,分情况进行讨论。原创 2023-02-16 15:29:23 · 151 阅读 · 0 评论 -
163、【动态规划】leetcode ——198. 打家劫舍(C++版本)
dp[i] = max(dp[i - 1], dp[i - 2] + nums[i]),因此相邻的数不能选择,最少隔一个选一个。dp[i - 1]:不选当前的i,选择上一个i-1,。dp[i - 2] + nums[i]:从上一个i - 2往后选择当前i,而不选择上一个i - 1。因为有i-1和i-2,因此从i=2开始遍历,一直到n-1(因为这次设置dp[0]具有一个含义,因此到n-1,而不是n)。从0-i中选择数,组成的最大总和。原创 2023-02-16 13:33:41 · 127 阅读 · 0 评论 -
162、【动态规划】AcWing ——4. 多重背包问题 I(C++版本)
遍历时候,在最内层设置一个for循环,寻找从一个都不选到选s[i]个第i个物品时,哪种情况取得最大价值。在01背包一维滚动数组的基础上,内层再多个for循环。原创 2023-02-15 20:17:21 · 137 阅读 · 0 评论 -
161、【动态规划】leetcode ——139. 单词拆分:回溯法+动态规划(C++版本)
当在s中下标为[i-1, j]时,有对应的单词在wordDict中并且前i-1个字符可被wordDcit组成时, 让dp[j] = true。为2,则应该得到为121才合法,如果得到的为112应不合法,不为我们的把目标。因此,这是一个考虑顺序的。取到s中第j个字符时,可以由wordDict所组成。背包为s字符串,物品为从当前0-j之间的字符。为了便于计算让dp[j] = true。因为需要考虑顺序问题,例如。,应该先背包再物品。原创 2023-02-15 18:26:05 · 148 阅读 · 0 评论 -
160、【动态规划】leetcode ——279. 完全平方数:二维数组+一维滚动数组(C++版本)
dp[i][j] = min(dp[i - 1][j], dp[i][j - i * i] + 1),完全背包的一般公式,因为最后求的是唯一的最小值,不需考虑顺序问题,先背包再物品,先物品再背包都可以,内层从小到大。因为求的是MIN,就要求都初始化为INT_MAX,再让dp[i][0] = 0,便于计算。在和为j的前提下,从1-i中选出对应的完全平方数,用最少的数组合出j,所使用的数的个数。:使用这个数的完全平方的情况加上一。此方式,在两三个用例中会超时。递推公式写为二维的等价式。原创 2023-02-14 20:01:03 · 178 阅读 · 0 评论 -
159、【动态规划】leetcode ——322. 零钱兑换:二维数组+一维滚动数组(C++版本)
dp[i][j] = min(dp[i - 1][j], dp[i][j - coins[i]]),完全背包递推公式取最小值。在总额为j的前提下,从coins[0]-coins[i]中选择硬币,可用最少硬币组成的j的硬币个数。因为要求的是最小值,因此dp[0][0] = 0, 其余都初始化为INT_MAX。因为只要找到某种最小值的方案取的是MIN,因此先背包后物品,先物品后背包都可以。,初始化与之相同,遍历顺序按完全背包滚动数组方式从小到大。将递推公式转化为等价式。原创 2023-02-14 16:24:07 · 266 阅读 · 0 评论 -
157、【动态规划】leetcode ——377. 组合总和 Ⅳ:二维数组+一维滚动数组(C++版本)
的遍历顺序时:先物品,再背包,从小到大遍历,内层要判定物品容量在规定范围内。的遍历顺序是:先背包,再物品,从小到大遍历。大致相同,区别之处在于,零钱兑换解决的是。对于解决完全背包累的一维滚动数组来说,原创 2023-02-13 21:51:30 · 359 阅读 · 0 评论 -
158、【动态规划】leetcode ——518. 零钱兑换 II:二维数组+一维滚动数组(C++版本)
这样子可以保证,每个按顺序被遍历一次。如果先背包再物品,则每个物品会被遍历多次,此时适于排列问题。内层按从小到大遍历。dp[i][0] = 1,从0-i中选择,构成总金额为0的仅有一种方案,这样子设置便于后续计算。从面值为coins[0]到coins[i]中选取,可以组成总金额为j的方案个数。,根据递推公式,在一次物品遍历时,可加上多次同一个物品。(不同顺序的相同元素,代表同一种情况),因此需要按。优化为一维滚动数组后,原创 2023-02-13 12:51:24 · 201 阅读 · 0 评论 -
156、【动态规划】AcWing ——3. 完全背包问题:二维数组+一维滚动数组(C++版本)
先背包再物品,或者先物品再背包都可以,顺序是从小到大,从而实现,在外层值固定时,内层for循环遍历过程中,可以加到之前已加上的数据信息。dp[i][j] = max(dp[i - 1][j], dp[i][j - v[i]] + w[i]),该公式是由两个公式联立而成。该公式是说明,在同一物品可多次选择的条件下,不选该物品和选择该物品时,取得一个最大价值的方案。dp[j] = max(dp[j], dp[j - v[i]] + w[i]),按照一定的遍历顺序要与二维中的公式等价。原创 2023-02-12 19:59:11 · 452 阅读 · 0 评论 -
155、【动态规划】leetcode ——474. 一和零:三维数组+二维滚动数组(C++版本)
如果是从小到大遍历的话,虽然第一次计算的结果会使i-1时的情况,但后续继续遍历时,由于j - zeros和k - ones可能会出现之前在i时遍历过程中已经被更新的情况,导致重复计数。而如果从大到小遍历的话,就可以保证每次遍历时都是按照i-1时的情况计算,并且在后续遍历时不会出现重复计数。,则该题就可以转化为01背包问题,其中m个0和n个1,可看作一个背包中两个不同维度的表示。本题是要在已有的字符串中,找到给定的m个0和n个1,组出最大的子集。因为一个字符串代表一个物品,其重量为1,原创 2023-02-12 15:43:03 · 419 阅读 · 0 评论