
dp 动态规划
文章平均质量分 54
csu_xiji
这个作者很懒,什么都没留下…
展开
-
力扣 1218. 最长定差子序列 哈希 dp
https://leetcode-cn.com/problems/longest-arithmetic-subsequence-of-given-difference/思路:其实和最长上升子序列是很像的,考虑dpidp_idpi表示以aia_iai结尾的最长等差子序列的长度,那么当j<ij<ij<i且aj=ai+da_j=a_i+daj=ai+d时有dpi=max(dpi,dpj+1)dp_i=max(dp_i,dp_j+1)dpi=max(dpi,dpj+1),但是这样原创 2021-11-06 02:09:45 · 381 阅读 · 0 评论 -
力扣 524. 通过删除字母匹配到字典里最长单词 dp
https://leetcode-cn.com/problems/longest-word-in-dictionary-through-deleting/思路:经典题目了,其实就是求满足题意的子序列嘛。直接预处理出dpi,jdp_{i,j}dpi,j数组,dpi,jdp_{i,j}dpi,j表示从第iii个位置开始第一个字符jjj所对应的位置,显然有:dpi,j={dpi,j=dpi+1,j, if si≠ jdpi,j=i,&nb原创 2021-09-15 01:47:14 · 141 阅读 · 0 评论 -
力扣 5865. 访问完所有房间的第一天 dp 前缀和优化
https://leetcode-cn.com/problems/first-day-where-you-have-been-in-all-the-rooms/思路:经典读错题+想歪。分析后不难发现,第一次到达房间iii,下一次必定要回到<=i<=i<=i的房间jjj(不妨把这个操作叫做回访),且此时<i<i<i的房间都到达了偶数次,那么对于[j,i)[j,i)[j,i)的每个房间,我们都需要再次回访,如果用dpidp_idpi表示在位置iii进行回访操作后再重新回原创 2021-09-06 01:33:23 · 160 阅读 · 0 评论 -
力扣 787. K 站中转内最便宜的航班 dp
https://leetcode-cn.com/problems/cheapest-flights-within-k-stops/思路:经典dpdpdp题想歪wa半天。考虑dpi,jdp_{i,j}dpi,j表示经过iii条边后到达点jjj的最便宜的价格。显然有dp0,src=0dp_{0,src}=0dp0,src=0,最终答案就是mini,dstmin_{i,dst}mini,dst,其中0<=i<=k+10<=i<=k+10<=i<=k+1。怎么转移呢?其原创 2021-08-27 02:14:47 · 140 阅读 · 0 评论 -
力扣 5836. 到达目的地的方案数 dijkstra+dp
https://leetcode-cn.com/problems/number-of-ways-to-arrive-at-destination/思路:可恶啊,没开longlong WAlonglong\ WAlonglong WA了几发。题目是求从起点到终点的最短路径的方案数,考虑在求最短路的过程中dpdpdp,用dpidp_idpi表示从起点到点iii的最短路径的方案数,由于此题中起点固定为0,因此可以令dp0=1dp_0=1dp0=1。在使用DijkstraDijkstra原创 2021-08-22 00:49:33 · 308 阅读 · 0 评论 -
力扣 552. 学生出勤记录 II dp / 矩阵快速幂
https://leetcode-cn.com/problems/student-attendance-record-ii/思路一:动态规划,dpi,j,kdp_{i,j,k}dpi,j,k表示前iii次出勤缺勤了jjj次且最后连续kkk次迟到情况下能获得出勤奖励的次数。因为当且仅当j<2&&k<3j<2 \&\&k<3j<2&&k<3时才有意义,所以总体复杂度依然是O(n)O(n)O(n)的。下面是状态转移方程的推导原创 2021-08-20 01:22:23 · 303 阅读 · 0 评论 -
力扣 576. 出界的路径数 dp
https://leetcode-cn.com/problems/out-of-boundary-paths/思路:非常简单的dpdpdp,考虑用dpi,j,kdp_{i,j,k}dpi,j,k表示经过iii次移动后到达坐标(j,k)(j,k)(j,k)的方案数,那么对于任意一个坐标(j,k)(j,k)(j,k),与其相邻的四个网格坐标即为一次移动后可能到达的点。转移方程比较简单,直接看代码吧。注意到dpidp_idpi只利用到了dpi−1dp_{i-1}dpi−1的信息,因此可以用滚动数组优化原创 2021-08-16 00:56:38 · 131 阅读 · 0 评论 -
力扣 516. 最长回文子序列 dp
https://leetcode-cn.com/problems/longest-palindromic-subsequence/思路一:dpi,jdp_{i,j}dpi,j表示区间[i,j][i,j][i,j]的最长回文子序列的长度,显然dpi,i=1dp_{i,i}=1dpi,i=1,对于区间[i,j][i,j][i,j]如果有si=sjs_i=s_jsi=sj,那么有dpi,j=dpi+1,j−1+2dp_{i,j}=dp_{i+1,j-1}+2dpi,j=dpi+1,j−1+2;否则原创 2021-08-13 00:50:25 · 158 阅读 · 0 评论 -
力扣 446. 等差数列划分 II - 子序列 dp
https://leetcode-cn.com/problems/arithmetic-slices-ii-subsequence/思路:就知道是dp,但是差一步没写出来,唉。考虑用dp[i][j]dp[i][j]dp[i][j]表示以nums[i]nums[i]nums[i]结尾公差为jjj的长度>=2>=2>=2的子序列个数。那么可以枚举等差数列的最后两项:numsj、numsinums_j、nums_inumsj、numsi。计算其公差dis=numsi−numsjdis=n原创 2021-08-11 01:46:27 · 172 阅读 · 0 评论 -
力扣 1713. 得到子序列的最少操作次数 贪心 哈希 LCS转LIS
https://leetcode-cn.com/problems/minimum-operations-to-make-a-subsequence/思路:如果序列a、ba、ba、b的最长公共子序列的长度为lenlenlen,且序列aaa的长度为nnn,那么最少需要的次数就等于n−lenn-lenn−len。但是我们所熟知的最长公共子序列解法的时间复杂度是O(n∗m)O(n*m)O(n∗m)的,显然本题的数据范围不允许这样做。注意到题目中的一个重要条件:aaa中的元素互不相同。那么我们可以通过函数:f(a原创 2021-07-26 20:18:03 · 153 阅读 · 0 评论 -
力扣 LCP 07. 传递信息 bfs/dfs/dp
https://leetcode-cn.com/problems/chuan-di-xin-xi/思路一:无脑遍历,dfs/bfs均可,时间复杂度O(nk)O(n^k)O(nk)。class Solution {public: int numWays(int n, vector<vector<int>>& relation, int k) { vector<vector<int>> vec(n,vector<int原创 2021-07-02 21:56:40 · 158 阅读 · 0 评论 -
力扣 279. 完全平方数 dp
https://leetcode-cn.com/problems/perfect-squares/思路:做法挺多的,就说一下dp吧。类似于完全背包的做法,只不过现在是求最小个数。用dpidp_idpi表示表示正整数iii所需要的最少个数,那么对于每个满足题意的完全平方数xxx,有:dpi=min(dpi,dpi−x+1)dp_i=min(dp_i,dp_{i-x}+1)dpi=min(dpi,dpi−x+1)class Solution {public: int numSqua原创 2021-06-11 00:54:29 · 92 阅读 · 0 评论 -
力扣 518. 零钱兑换 II dp
https://leetcode-cn.com/problems/coin-change-2/思路:经典完全背包问题……class Solution {public: int change(int amount, vector<int>& coins) { vector<int> dp(amount+1); dp[0]=1; for(const int &coin:coins) {原创 2021-06-10 17:04:10 · 129 阅读 · 0 评论 -
力扣 1049. 最后一块石头的重量 II dp
https://leetcode-cn.com/problems/last-stone-weight-ii/思路:考虑dpi,jdp_{i,j}dpi,j表示处理前iii个石块后剩余石块重量总和为jjj的状态是否存在。那么对于dpi−1,jdp_{i-1,j}dpi−1,j,我们可以把第iii块石头加进来但不做任何处理,也可以粉碎第iii块石头(这取决于stonesistones_istonesi和jjj的大小),因此有转移方程:dpi,j+stonesi=dpi−1,jdpi,abs(j−st原创 2021-06-10 16:51:49 · 220 阅读 · 0 评论 -
力扣 879. 盈利计划 dp
https://leetcode-cn.com/problems/profitable-schemes/思路:依旧和01背包问题很像,考虑用dpi,j,kdp_{i,j,k}dpi,j,k表示前iii种工作使用了jjj名员工且利润为kkk的方案数,在不考虑取模的情况下,如果当前的j、kj、kj、k不满足第iii种工作的限制,那么有:dpi,j,k=dpi−1,j,kdp_{i,j,k}=dp_{i-1,j,k}dpi,j,k=dpi−1,j,k否则有:dpi,j,k=dpi−1,j,k+原创 2021-06-10 00:35:04 · 176 阅读 · 0 评论 -
力扣 1787. 使所有区间的异或结果为零 dp 位运算
https://leetcode-cn.com/problems/make-the-xor-of-all-segments-equal-to-zero/思路:依据题意,有:nums[i] xor nums[i+1]……xor nums[i+k−1]=0 (1)nums[i+1] xor nums[i+2]……xor nums[i+k]=0 (2)nums[i]\ xor\原创 2021-06-07 22:41:25 · 147 阅读 · 0 评论 -
力扣 664. 奇怪的打印机 区间dp
https://leetcode-cn.com/problems/strange-printer/思路:dp还是不太熟悉呀……考虑用dpi,jdp_{i,j}dpi,j表示打印区间[i,j][i,j][i,j]所需要的最少次数,那么显然dpi,i=1dp_{i,i}=1dpi,i=1,对于区间[i,j][i,j][i,j],枚举断点kkk,有dpi,j=min(dpi,k+dpk+1,j)dp_{i,j}=min(dp_{i,k}+dp_{k+1,j})dpi,j=min(dpi,k+dpk+1原创 2021-06-07 02:34:21 · 314 阅读 · 0 评论 -
力扣 474. 一和零 dp(二维01背包)
https://leetcode-cn.com/problems/ones-and-zeroes/思路:太久没写背包了,都有点忘了……把每个字符串的0、1个数抽象为代价,m、n抽象为背包容量上限,显然就是二维01背包问题,做法和一维背包类似。class Solution {public: int findMaxForm(vector<string>& strs, int m, int n) { using pr=pair<int,int>;原创 2021-06-06 01:42:37 · 213 阅读 · 0 评论 -
力扣 1035. 不相交的线 dp
https://leetcode-cn.com/problems/uncrossed-lines/思路:两个要点,第一是连线对应位置的数相等,第二是线与线之间不相交,说明相对位置是一样的。那么其实这道题就是在求两个序列的最长公共子序列。class Solution {public: int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) { int n=nums1.si原创 2021-05-22 19:47:03 · 240 阅读 · 0 评论 -
力扣 1269. 停在原地的方案数 dp
https://leetcode-cn.com/problems/number-of-ways-to-stay-in-the-same-place-after-some-steps/思路:dpi,jdp_{i,j}dpi,j表示经过iii步后到达jjj位置的方法数,显然 dp0,0=1dp_{0,0}=1dp0,0=1,且有以下转移方程:dpi,j=dpi−1,j−1+dpi−1,j+dpi−1,j+1dp_{i,j}=dp_{i-1,j-1}+dp_{i-1,j}+dp_{i-1,j+1}d原创 2021-05-13 16:06:52 · 74 阅读 · 0 评论 -
力扣 403. 青蛙过河 记忆化搜索/dp
https://leetcode-cn.com/problems/frog-jump/思路一:记忆化搜索应该是比较直观的,就是给爆搜加了一个记忆化的优化,用vis[i][j]vis[i][j]vis[i][j]记录在第iii块石子上跳jjj步是否有解,然后就是比较常见的搜索写法了,不多赘述。class Solution {public: vector<unordered_map<int,bool>> vis; bool dfs(vector<int&原创 2021-04-29 04:03:20 · 275 阅读 · 0 评论 -
力扣 377. 组合总和 Ⅳ dp
https://leetcode-cn.com/problems/combination-sum-iv/思路:类似于进阶的跳楼梯问题。dpidp_idpi表示总和为iii的组合(实际上按照题意应该是排列)个数,那么对于所有的numsjnums_jnumsj,只要numsj<=inums_j<=inumsj<=i就有dpi=dpi+dpi−numsjdp_i=dp_i+dp_{i-nums_j}dpi=dpi+dpi−numsj。初始令dp0=1dp_0=1dp0=1即可原创 2021-04-24 01:30:28 · 159 阅读 · 0 评论 -
力扣 368. 最大整除子集 dp DAG上最长路
https://leetcode-cn.com/problems/largest-divisible-subset/思路:若nums[i]nums[i]nums[i]可以整除nums[j]nums[j]nums[j],我们认为从iii到jjj有一条边,那么O(n2)O(n^2)O(n2)处理数组后就得到了一张图,问题就转换为求这张图上的最长路径。有两种做法,第一spfa求最长路;第二先把图转换为有向无环图,然后利用dp求DAG上最长路。先给出第一种做法的代码:class Solution {publ原创 2021-04-23 14:58:51 · 176 阅读 · 0 评论 -
力扣 91. 解码方法 dp
https://leetcode-cn.com/problems/decode-ways/思路:dp[i]dp[i]dp[i]表示字符串s[0……i)s[0……i)s[0……i)的解码方法的总数,那么对于s[i]s[i]s[i],如果它不等于字符0,显然它可以单独解码为一个字符,所以dp[i]=dp[i−1]dp[i]=dp[i-1]dp[i]=dp[i−1];再考虑s[i−1]、s[i]s[i-1]、s[i]s[i−1]、s[i],如果这两个连起来可以解码为11−2611-2611−26中的某个字符,原创 2021-04-21 19:16:53 · 183 阅读 · 0 评论 -
力扣 87. 扰乱字符串 记忆化搜索 思维
https://leetcode-cn.com/problems/scramble-string/思路:先定义一种字符串之间的相似运算:如果字符串a、b长度相等且含有的字符都相同,我们认为a和b相似。显然如果s、t互为扰乱字符串,则它们一定相似。从扰乱字符串的规则可以发现,如果断点是i,那么至少满足以下两种情况的某一种:s[0…i]、t[0…i]s[0…i]、t[0…i]s[0…i]、t[0…i]相似且s[i+1…n)、t[i+1…n)s[i+1…n)、t[i+1…n)s[i+1…n)、t[i+1…原创 2021-04-17 01:29:29 · 154 阅读 · 0 评论 -
力扣 264. 丑数 II dp
https://leetcode-cn.com/problems/ugly-number-ii/思路:dpidp_idpi表示第i个丑数的值,显然它是一个单调递增的数组,用idx1、idx2、idx3idx_1、idx_2、idx_3idx1、idx2、idx3记录按照∗2、∗3、∗5*2、*3、*5∗2、∗3、∗5方式扩展的上个丑数的下标,显然dpidp_idpi要取最小的那个值。class Solution {public: int nthUglyNumber(int n) {原创 2021-04-11 01:41:09 · 202 阅读 · 0 评论 -
力扣 115. 不同的子序列 dp
https://leetcode-cn.com/problems/distinct-subsequences/思路:dpijdp_{ij}dpij表示s[i:]s[i:]s[i:]的子序列中t[j:]t[j:]t[j:]出现的次数,那么初始时dp[i][m]=1dp[i][m]=1dp[i][m]=1,当s[i]=t[j]s[i]=t[j]s[i]=t[j]时,t[j]t[j]t[j]可以选择是否与s[i]s[i]s[i]匹配,从而得到dp[i][j]=dp[i+1][j+1]+dp[i+1][j]d原创 2021-03-17 15:22:34 · 118 阅读 · 0 评论 -
力扣 132. 分割回文串 II dp bfs/dfs 剪枝
https://leetcode-cn.com/problems/palindrome-partitioning-ii/思路一:先O(n2)O(n^2)O(n2)预处理出dpdpdp数组,若s[i…j]s[i…j]s[i…j]是回文串,则dpij=1dp_{ij}=1dpij=1。我们可以把这个数组当作一个邻接矩阵,即把dpij=1dp_{ij}=1dpij=1抽象为iii到jjj的一条边,最终可以得到一个图,那么答案就等于从000开始到n−1n-1n−1的最短路径,直接bfsbfsbfs即可。c原创 2021-03-08 23:49:08 · 164 阅读 · 0 评论 -
力扣 131. 分割回文串 dp 回溯
https://leetcode-cn.com/problems/palindrome-partitioning/思路:先dpdpdp进行预处理,如果s[i…j]s[i…j]s[i…j]是回文串就令dp[i][j]=1dp[i][j]=1dp[i][j]=1,详情看这篇博客。然后很显然就是搜索了吧……回溯法感觉也没多少好讲的……class Solution {public: void dfs(vector<vector<string>> &ans,vecto原创 2021-03-08 01:15:40 · 135 阅读 · 0 评论 -
力扣 5. 最长回文子串 dp 马拉车算法
https://leetcode-cn.com/problems/longest-palindromic-substring/思路一:dpdpdp,如果s[i…j]s[i…j]s[i…j]是回文串,那么dp[i][j]=1dp[i][j]=1dp[i][j]=1,否则dp[i][j]=0dp[i][j]=0dp[i][j]=0,显然dp[i][i]=1dp[i][i]=1dp[i][i]=1,接下来枚举区间长度lenlenlen和起始点iii,那么终止点就是j=i+len−1j=i+len-1j=i+le原创 2021-03-07 17:29:44 · 161 阅读 · 0 评论 -
PIPIOJ 1486: 地头蛇PIPI II dp
http://www.pipioj.online/problem.php?id=1486思路:dpdpdp,如果商店没有连成环,那么转移公式为:dpi=max(dpi−2+ai,dpi−1)dp_i=max(dp_{i-2}+a_i,dp_{i-1})dpi=max(dpi−2+ai,dpi−1)。连成环的话就是第一个和最后一个不能同时取嘛,美剧两种情况即可,转移公式不变。#include<bits/stdc++.h>#define INF 0x3f3f3f3fusing na原创 2021-03-05 16:14:11 · 166 阅读 · 0 评论 -
力扣 354. 俄罗斯套娃信封问题 LIS sort
https://leetcode-cn.com/problems/russian-doll-envelopes/思路:先按照www从小到大对输入进行排序,那么问题就转换成了LISLISLIS,但是还有一些地方需要注意,套娃时信封的w、hw、hw、h要求都是单调递增的,所以排序后www相等的信封只能选111个,怎么保证这一点呢?在www相等时,我们可以按照hhh从大到小排序,这样在计算LISLISLIS时相同wewewe的信封一定最多选一个。class Solution {public: in原创 2021-03-04 16:36:16 · 179 阅读 · 1 评论 -
力扣 338. 比特位计数 位运算 dp
https://leetcode-cn.com/problems/counting-bits/思路一:一个数可以通过2的幂次的和来表示出来,那么假设当前增加的数为addaddadd,通过枚举所有大于addaddadd且小于等于numnumnum的2的幂次就可以递推出新的数。class Solution {public: vector<int> countBits(int num) { vector<int> ans(num+1); in原创 2021-03-03 20:18:28 · 229 阅读 · 1 评论 -
力扣 978. 最长湍流子数组 滑动窗口 dp
https://leetcode-cn.com/problems/longest-turbulent-subarray/思路一:滑动窗口。先只考虑第一种情况,我们可以维护一个满足题意的窗口[l,r)[l,r)[l,r),每次检测arr[r−1]、arr[r]arr[r-1]、arr[r]arr[r−1]、arr[r]是否满足定义,若满足则令r=r+1r=r+1r=r+1,否则说明区间[l,r][l,r][l,r]不满足题意了,那么可以令l=r,r=r+1l=r,r=r+1l=r,r=r+1。第二种情况类原创 2021-02-08 21:04:58 · 116 阅读 · 0 评论 -
力扣 392. 判断子序列 dp/双指针
https://leetcode-cn.com/problems/is-subsequence/思路:有一个显然正确的贪心:对于任意一个字符iii,假设可选的匹配位置有pos1、pos2pos_1、pos_2pos1、pos2,且pos1<pos2pos_1<pos_2pos1<pos2,那么应该选择pos1pos_1pos1而不是pos2pos_2pos2。双指针的做法就不说了,说一下后续挑战怎么搞。第一个思路我们用vec[i][j]vec[i][j]vec[i][j]记原创 2020-10-08 18:54:45 · 260 阅读 · 0 评论 -
力扣 1025. 除数博弈 dp/博弈
https://leetcode-cn.com/problems/divisor-game/思路一:dpdpdp,不妨设dp[i]dp[i]dp[i]表示数字为iii时,爱丽丝能否胜利。那么显然有dp[1]=falsedp[1]=falsedp[1]=false,dp[2]=truedp[2]=truedp[2]=true,对于任意的3<=i<=N3<=i<=N3<=i<=N,对于其任意一个因子jjj显然有dp[i]=dp[i]∣∣dp[i−j]dp[i]=dp[i]原创 2020-10-08 00:25:53 · 206 阅读 · 0 评论 -
力扣 面试题 08.14. 布尔运算 区间dp
https://leetcode-cn.com/problems/boolean-evaluation-lcci/思路:看数据范围应该可以暴力枚举,不过我们还是用dpdpdp吧。dp[i][j][0]dp[i][j][0]dp[i][j][0]等于使[i,j][i,j][i,j]的表达式得出000的括号方法数,dp[i][j][1]dp[i][j][1]dp[i][j][1]等于使[i,j][i,j][i,j]的表达式得出111的括号方法数。枚举断点kkk,s[k]s[k]s[k]对应不同的运算符时有不原创 2020-08-22 00:35:55 · 340 阅读 · 0 评论 -
力扣 96. 不同的二叉搜索树 dp/卡特兰数
思路一:dpdpdp,设dp[i]dp[i]dp[i]表示任意iii个不相等的节点所能组成的二叉搜索树的个数。因为在二叉搜索树中,我们并不关心某个节点的值,而是关心它们之间的大小关系,所以节点1、21、21、2能组成的二叉搜索树的个数和节点1、31、31、3能组成的二叉搜索树的个数是相等的。那么对于以1…n1…n1…n为节点的二叉搜索树,我们可以枚举根节点iii:当根节点为iii时,左子树有i−1i-1i−1个节点,右子树有n−in-in−i个节点,所以有:dp[i]=∑j=1idp[j−1]∗dp[i−.原创 2020-07-08 00:43:33 · 229 阅读 · 0 评论 -
力扣 523. 连续的子数组和 hash+dp
https://leetcode-cn.com/problems/continuous-subarray-sum/思路:hash+dphash+dphash+dp。搞一个hashhashhash表,dp[sum]=idp[sum]=idp[sum]=i,表示[0…i][0…i][0…i]的前缀和si%k=sums_i\%k=sumsi%k=sum,初始可以令dp[0]=−1dp[0]=-1dp[0]=−1,然后遍历整个数组,记录前缀和sis_isi,如果dp[si%k]dp[s_i\%k]dp[si原创 2020-05-13 01:38:36 · 397 阅读 · 0 评论 -
力扣 312. 戳气球 区间dp
https://leetcode-cn.com/problems/burst-balloons/思路:设dp[i][j]dp[i][j]dp[i][j]表示戳破区间[i,j][i,j][i,j]的所有气球所能获得的最大硬币数。为了方便处理,我们在数组开头和结尾各放入一个111,设数组原来有nnn个元素,显然答案为dp[1][n]dp[1][n]dp[1][n]。那么对于区间[i,j][i,j]...原创 2020-04-26 01:38:13 · 357 阅读 · 0 评论