动态规划
文章平均质量分 61
动态规划
_九磅十五便士_
这个作者很懒,什么都没留下…
展开
-
AtCoder Beginner Contest 259 F - Select Edges(树形dp)
树形dp原创 2022-07-10 17:11:57 · 535 阅读 · 0 评论 -
第十三届蓝桥杯-李白打酒加强版(dp)
一共最多有200个位置,每一个位置可以选择:加倍或者-1。加倍只能加n次,那么我们可以考虑定义状态dp[i][j][flag]dp[i][j][flag]dp[i][j][flag]表示第i个位置还有j次可以加倍,当前的操作选择的是flag,flag=0代表-1,flag=1代表加倍的种类数。但是如果当前定义的状态,那么信息不够,因为题目最终要问的是最后一次遇到花,而且刚好全部喝完酒了有多少种可能。我们还需要开设一个维度,代表当前还剩下多少酒。也就是dp[i][j][k][flag]dp[i][j.原创 2022-04-10 14:11:50 · 869 阅读 · 3 评论 -
VA1626 括号序列 Brackets sequence(区间dp)
题目传送门这道题有两个难点如何找到当前区间最小的添加值现在我们使用两个指针i,ji,ji,j,用这个两个指针dp[i][j]dp[i][j]dp[i][j]来记录一下,如果s[i],s[j]s[i],s[j]s[i],s[j]是合法的一对括号序列,那么状态转移方程就是:dp[i][j]=min(dp[i][j],dp[i+1][j−1])dp[i][j]=min(dp[i][j],dp[i+1][j-1])dp[i][j]=min(dp[i][j],dp[i+1][j−1])然而对于所有情况来说,原创 2021-10-09 17:31:59 · 144 阅读 · 0 评论 -
CF1509C The Sports Festival(dp+思维)
题目传送门题意给你一个序列,你可以任意交换这个序列的位置,现在让你求出前n个子序列的最大值减去最小值之和的最小值。思路这道题要求前n个子序列的最大值减去最小值最小,那么贪心考虑我们肯定尽量让最小值或者最大值在最后,如果不然,那么我们最大值-最小值(差值最大)的情况将会有两种,因此,将进行区间dp。#include<iostream>#include<algorithm>#define int unsigned long longusing namespace std;原创 2021-08-09 14:46:11 · 192 阅读 · 0 评论 -
CF1548C The Three Little Pigs(组合数学+dp)
题目传送门题意这道题实际上就是让求∑i=1nC3∗ix,x\displaystyle\sum_{i=1}^{n}C_{3*i}^x,xi=1∑nC3∗ix,x是我们每次询问的数值,nnn是小猪进场的轮数。思路我们可以定义一个dpdpdp方程,dp[x][m]dp[x][m]dp[x][m]代表∑i=1n−1C3∗i+mx\displaystyle\sum_{i=1}^{n-1}C_{3*i+m}^xi=1∑n−1C3∗i+mx因此,我们可以得到dp[x][0]+dp[x][1]+dp[x]原创 2021-08-03 12:24:53 · 293 阅读 · 0 评论 -
2021牛客多校5-Double Strings(dp+组合数学)
这道题不要读假题呀,这道题不是让你选连续的一段(要是连续的一段不就成签到题了么)dp思路用dp[i][j]dp[i][j]dp[i][j]表示只考虑 AAA中的前iii个字符和BBB中的前jjj个字符时的相同的子序列的个数。状态转移如下:dp[i][j]=dp[i−1][j]+dp[i][j−1]−dp[i−1][j−1]dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]dp[i][j]=dp[i−1][j]+dp[i][j−1]−dp[i−1][j−1]...原创 2021-08-01 13:20:08 · 157 阅读 · 0 评论 -
CF1551E Fixed Points (DP)
题目传送门题意在每一组测试中,第一行给你两个数n,k,第二行给你一个大小为n的数组要求你可以删一些数,至少有k个能满足,a[i]=i,请问删除的数最少有几个,如果没有这样的数字,输出-1思路这道题其实很容易能看出来这是一个dp,但是我们应该怎么分析呢?首先对于dp[i][j]代表前i个数,删除第j个了以后有几个满足这样的情况。1.我们这个点不删if(a[i]==i−j)if(a[i]==i-j)if(a[i]==i−j)dp[i][j]=dp[i−1][j]+1dp[i][j]=dp[i-1原创 2021-07-27 10:08:08 · 163 阅读 · 0 评论 -
CF1221D Make The Fence Great Again(DP)
题目传送门这道题其实也分析出来了,就是dp[n][3]的一个空间,最多修2个单位长度,最少不修,状态转移其实不难,但是这道题做成了dp大讨论(哭)。#include<iostream>#include<cstring>using namespace std;typedef long long ll;ll dp[355555][3];ll a[2102100];ll b[2102100];int main(){ int T; cin>>T; whil原创 2021-07-16 16:20:53 · 100 阅读 · 0 评论 -
AtCoder Beginner Contest 208 E - Digit Products(数位dp)
题目传送门这道题就是一个数位dp,其实也挺容易看出来,但是针对于记搜的过程中1~1e9有点太大了,数组没有办法开到那么大,因此我们需要离散化,map离散化就可以了记忆化搜索那么我们需要记录一下前导0(如果从前面开始一直是0就不会影响最后的每一位的乘数),如果是中间为0的话那么我们这个结果就是0。还要记录一下当前状态的乘数,当然还有搜索到的位数。总体来说是一个比较基础的数位dp,我错的思路在注释里写了。#include<iostream>#include<cstring>原创 2021-07-05 16:11:07 · 476 阅读 · 0 评论 -
CF1535C Unstable String(dp)
题目传送门可以说是比较简单的一道dp问题了但是还是没做出来就很菜了。dp[i][j]来存第i个位置对于答案的贡献,状态转移是dp[i][j]=dp[i-1][j1]+1,因为dp[i-1][j1]存的是i-1向前延申最多位所能有的最多的子串。因此加上它本身又来一位的值。因为答案问的是最大值,所以到后面求一个最大值即可。#include<iostream>#include<cstring>using namespace std;int dp[210200][2];cha原创 2021-06-06 23:20:11 · 215 阅读 · 2 评论 -
CF1512G Short Task(数论+dp)
题目传送门等我上完课回来再写题解~#include<iostream>using namespace std;typedef long long ll;const int N=1e7+1000;int primes[N], cnt; // primes[]存储所有素数bool st[N]; // st[x]存储x是否被筛掉ll dp[N];int ans[N];void get_primes(int n){ for (int i = 2; i原创 2021-06-04 13:48:36 · 132 阅读 · 0 评论 -
CF1528B Kavi on Pairing Duty(dp)
题目传送门思路这道题真的是一道不太好想的dp…真的太菜了首先状态转移分成两种情况区间长度相等的情况,如这种情况就是看看你现在的区间有几个约数,那么代表有几种这样的situation记为v[i]包含情况,如dp[i]+=dp[i-1]dp[i]+=dp[i-1]这样的就是dp[i]+=dp[i-1]+dp[i-2]当然还有这样的这样的就是,两个区间交替,外层区间谁也没有包谁那么就是dp[i]+=dp[i-2]那么状态转移方程就是dp[i]=dp[i−1]原创 2021-05-31 23:17:34 · 257 阅读 · 1 评论 -
CF1498C Planar Reflections(思维+dp)
题目传送门思路设定dp[i][j]dp[i][j]dp[i][j]代表的是现在有一个以jjj为能级的原子,前面有iii个能级墙,经过这个过程以后能产生的原子。首先dpdpdp问题就应该分析状态,任意一个状态来看,经过一个能级墙所能产生的原子是:1状态上一个和初始状态相同的方向的所经过这里产生的dp[i−1][j]dp[i-1][j]dp[i−1][j]还有一种就是原子分裂产生的新的更弱能级,计算方式就是这个更弱能级产生的其实就是更小的能级j-1,而且这个原子面对的方向和我们初始的方向其实是相反的原创 2021-05-31 19:30:28 · 128 阅读 · 1 评论 -
CF1238C Standard Free2play(dp)
题目传送门题意这道题的题意我感觉还是挺不好理解的意思就是说现在给你一个悬崖,每个样例中第二行输入的数代表这个悬崖突出的部分,你刚好站着这个悬崖的最高层,现在你可以进行如下操作:将本突起位置隐藏,(这样你就掉下去了)但是做出的代价就是让这个位置的紧挨着的下一个位置的状态发生改变(如果你改变了x位置的突出情况,如果x-1位置是突出的,那么它将变成隐藏的,反之就会变成突出的)但是现在有一个问题就是你是绝对不能允许你往下掉两个单位,因为你是bym同学,那样会影响到你的发型,(这样就无法吸引别人追求你),当然你原创 2021-05-30 21:28:29 · 128 阅读 · 0 评论 -
CF1516C Baby Ehab Partitions Again(思维+dp)
题目传送门思路现在分析一下,对所有元素先求一遍和,其结果是奇数,那么代表不用修改任何值(因为奇数你本身就无法做到平均分配),那么这个数组就一定是一个好数组。如果是偶数的话,就需要用到dp,如果dp[sum/2]是真值,那么对整个数组进行遍历,每一次遍历的过程中就是寻找奇数,如果找到了奇数,就代表这个子状态没有办法平均分配这些数字。那么其去掉这个数,对于数组中的任何数据乘上这个相应的倍数都无法做到平均分配,因此输出这个数组的下标即可。#include<iostream>#include&原创 2021-05-30 19:05:09 · 289 阅读 · 0 评论 -
CF1282B2 K for the Price of One (Hard Version)(dp)
题目传送门题意有n个商品,每个商品价值为 ai 现在有一个活动优惠,买一个物品可以选择k - 1个价值小于等于该它的物品免费获得(要么一个也不选,要么一定要选k - 1个),求k个硬币一共能买多少物品。在该题中k <= n。思路这道题我感觉是一道很巧妙的题首先要明确的一点就是,我要买更多的东西,我现在的钱可以买贵的也可以买便宜的东西,那么我现在优先买什么?(不考虑免费拿的问题)一定先买便宜的,因为,我买了便宜的东西,我可能还有闲钱去买其他便宜的东西,但是我如果先买贵的东西,那么就不一定有闲原创 2021-05-30 11:20:23 · 68 阅读 · 0 评论 -
CF888D Almost Identity Permutations(dp)
题目传送门题意给出n和k计算满足至少有(n-k)个位置的值a[i]==i的1~n的全排列的个数。参考大佬博客思路这道题可以用dp去完成dp[i][j]dp[i][j]dp[i][j]表示序列是以i为长度的,只有j个a[k]=ka[k]=ka[k]=k的排列数那么我们想一下状态转移:dp[i][j]dp[i][j]dp[i][j]可以由dp[i−1][j],dp[i−1][j−1],dp[i−1][j+1]dp[i-1][j],dp[i-1][j-1],dp[i-1][j+1]dp[i−1][原创 2021-05-30 11:05:30 · 109 阅读 · 0 评论 -
CF913C Party Lemonade(贪心+dp)
题目传送门题意这道题类似于一个多重背包问题这道题大致意思就是:输入n,m,n代表有几种柠檬水m代表我现在举办聚会需要几升柠檬水下面的每一个数据代表2i(0<=i<n)2^i(0<=i<n)2i(0<=i<n)升柠檬水需要多少钱最后输出能满足聚会要求的(可以多买)柠檬水最少要多少钱思路这道题有一个非常巧妙的贪心+dp的做法。首先可以用dp的做法求出我们买每一组柠檬水要的最少价格比如,我买1L柠檬水需要1元钱,但是2L一块买就需要4块钱,那么我们可以用状态原创 2021-05-29 17:38:28 · 139 阅读 · 0 评论 -
CF1196D2 RGB Substring (hard version)(dp+前缀和思想)
题目传送门题意这道题的题意大致就是说第一行输入两个数n,k那么第一个数代表这个字符串的长度,第二个k代表这个字符串的子串的长度,而且要求这个字串必须是RGBRGBRGBRGBRGB...RGBRGBRGBRGBRGB...RGBRGBRGBRGBRGB...的一个字串,请问你最少可以修改几个字符,然后让这个字串也是这样的。思路这道题还是一个dp,那么如何去分析这道题呢?首先我们要想到,每一位上的字符都有可能是以R,G,B这三个字母为起点往后延伸k位,考虑动态规划解决本问题,那么就应该这么考虑:原创 2021-05-29 11:53:15 · 66 阅读 · 0 评论 -
CF1395C Boboniu and Bit Operations(线性dp)
题目传送门题意这个题的意思是说给你两个数组a和b,长度分别为n和m,现在你需要找到一个序列c长度为n,ci=aic_i=a_ici=ai & bk(1<=k<=m)b_k(1<=k<=m)bk(1<=k<=m)求出的最小值思路这个题就是dp,但是我个人认为还是不太好想。dp[i][j]=0/1dp[i][j]=0/1dp[i][j]=0/1代表前cic_ici个单位是否存在c1∣c2∣...∣ci=jc_1|c_2|...|c_i=jc1原创 2021-05-29 10:50:32 · 641 阅读 · 0 评论 -
CF1519D Maximum Sum of Products(基础区间dp)
题目传送门题意就是你可以任意reverse一个区间,求出ai∗bia_i*b_iai∗bi的最大值(反转之后的)思路这道题是一个区间dp,首先我们用两个指针来枚举左区间和右区间,然后用子状态(区间dp来分析反转情况)分析出状态转移就是dp[反转之后]=dp[反转之前]+a[i]∗b[j]+a[j]∗b[i]−a[i]∗b[i]−a[j]∗b[j]dp[反转之后]=dp[反转之前]+a[i]*b[j]+a[j]*b[i]-a[i]*b[i]-a[j]*b[j]dp[反转之后]=dp[反转之前]+原创 2021-05-29 09:54:31 · 169 阅读 · 0 评论 -
CF1497E2 Square-free division (hard version)(思维+dp+双指针预处理)
题目传送门题意相比于easy version唯一不同的地方在于k的非0,也就是你可以在这n个数任意选择k个数,变成其他的数字,求出最少的区间数。思路这道题的dp还真的挺难的,当时就觉得easy version出来了,hard version搏一搏hhhc这道题用dp[i][j]代表前i个数使用j次改变数值的权利的区间最小数dp[i][j]代表前i个数使用j次改变数值的权利的区间最小数dp[i][j]代表前i个数使用j次改变数值的权利的区间最小数那么状态转移方程就是dp[i][j]=min(d原创 2021-05-22 16:35:18 · 183 阅读 · 0 评论 -
CF1525D Armchairs(dp)
题目传送门题意简述就是给你一个01字串,每一次把1的位置挪到0的位置的代价是|i-j|总代价是加和,请问把所有1的位置,挪动到0的位置的代价最小值?思路本题可以将0的位置和1的位置分割开来分析dp[i][j]代表将前i个1挪动到前j个0的位置的代价最小值。那么我们就可以列出状态转移方程dp[i][j]=min(dp[i][j−1],dp[i−1][j−1]+abs(p1[i]−p0[j])dp[i][j]=min(dp[i][j-1],dp[i-1][j-1]+abs(p1[i]-p0[j]原创 2021-05-19 21:17:10 · 187 阅读 · 2 评论 -
美丽序列(线性dp)
题目传送门感觉这个题的dp不是很好想(牛客的题目怎么都这么鬼畜的说?)需要开一个四维dp数组dp[i][j][k][m]意思就是第i个数字为j的而且连续k个单调递减的和为m的美丽序列的个数。其中代码实现还是非常考验人的。其实状态转移真的不难想,但是主要是要开一个四维数组这个不容易想到。#include<iostream>using namespace std;typedef long long ll;ll dp[42][42][3][1601];ll a[210];cons原创 2021-05-18 23:43:19 · 173 阅读 · 0 评论 -
CF1077F2 Pictures with Kittens (hard version)(单调队列+dp优化)
题目传送门唉,曾经觉得单调队列学的没啥用。。。题目大意这个题目的意思就是说:给你一个数列a,你需要选择s个元素,使得连续的k个元素都至少有一个被选中。需要你最大化选出来的所有数的和。也就是滑动窗口问题:一个k单位大小的窗口,每一个窗口必须有数字选中,求最大和。思路这道题我也没有思路。。还看题解聚聚们的做法:这就是用单调队列,先模拟一下滑动窗口.这里参考一下大佬的博客,我觉得非常清楚易懂!大佬博客传送门至此,我想解释一下为什么在单调队列搞掉队尾元素的情况下,为什么要用dp数组来原创 2021-05-02 18:10:44 · 216 阅读 · 0 评论 -
被3整除的子序列(dp)
题目传送门这道题,难点在于状态的划分:开一个dp[n][3]大小的数组,后边用来存第i个字符之前的所有的子串的余数,当然可以选这个数,也可以不选。不多逼逼,上代码(比较好理解)#include<iostream>#include<cstring>using namespace std;const int modd=1e9+7;char s[210];int dp[2102][3];int main(){ cin>>s+1; int n=st原创 2021-04-29 21:34:16 · 168 阅读 · 0 评论 -
codeforces (背包dp+贪心)
题目传送门这个题,有一个易错点就是要根据优先级排序。这道题一看就是个01背包,但是问题是01背包问题是按照给定的数组顺序进行排序的,也就是说,选或者不选,你的顺序都是确定的,不能变:例如1 2 3 4 5按照01背包问题可以选择1 2 5但是答案是2 1 5(因为不同的时间做题得分不一样codeforces一大特点)因此要先按照优先级进行有针对性地排序:如何实现这个操作呢?现在给你两个数据:1:最高得分a1,每分钟减去的得分b1,和做这道题要用的时间c12:a2,b2,c2同理那么先原创 2021-04-29 21:11:34 · 250 阅读 · 0 评论 -
HDU1024 Max Sum Plus Plus (dp)
又是做不出来的一道dp传送门这个题目的思路就是:dp[n][m]:前n个数分成m组的最大值但是因为本题的数据范围,所以不能用二维数组,必须要用一维数组来对空间进行优化。那么利用两重循环for(int i=1;i<=m;i++){ for(int j=i;j<=n;j++) { dp[j]//这个意思是前j个数分成i组的最大值 //dp数组和g数组区别是:在本次循环中,dp[j-1]代表的是: //前j-1个数,分成i组的最大值,那么a[j]就并在前一组了 //g[原创 2021-04-14 09:01:45 · 110 阅读 · 0 评论 -
CF1513C Add One (dp+思维)
题目传送门这道题有点巧妙的说,本题的难点,我认为主要在状态的划分和状态转移方程的确定(话说所有dp问题不都应该是这个难点么hhhhhc)首先确定两个集合:1.dp[0][]这个集合代表的是最开始的状态从‘0’可以到最后衍生出来几位的数字2.dp[1][]这个集合代表的是最开始的状态从‘1’可以到最后衍生出来几位的数字当然这个数组的第二维代表是对这个数实施了几次的增加操作...原创 2021-04-12 19:41:39 · 342 阅读 · 1 评论 -
P4285 [SHOI2008]汉诺塔(线性dp)
题目传送门这道题可以用dfsdfsdfs做,也可以用dpdpdp来完成,本题解先使用dpdpdp来达成目标。但是真难哇,不愧是紫题呜呜呜。dp[i][a]dp[i][a]dp[i][a]表示把这一层上面的iii个盘子从aaa柱子挪动到别的柱子需要的移动次数,p[i][a]p[i][a]p[i][a]表示这上面的i个盘子要移动到哪个柱子(1,2,3)(1,2,3)(1,2,3)假设现在要移动aaa柱子上面的盘子。那么需要更新状态将i−1i-1i−1个盘子移动到p[i−1][a]p[i-1][a]p[原创 2021-03-31 13:27:36 · 197 阅读 · 0 评论 -
P1941 [NOIP2014 提高组] 飞扬的小鸟(线性dp+思维)
题目传送门注意读题:1.每一个单位时间可以点击多次(每一个单位时间可上升多次)。2.如果不点,那么每一个单位时间只能下降一次。分析状态:题干中要求问的是最少点击次数,那么我们看dp怎么想这个问题:dp[i][j],代表的是当前到达横坐标i,高度为j的点的时候最少的点击次数,那么我们看当前状态是通过什么状态转移而来的:1.下降到这里来的。(该情况一定是由上次转化而来的)状态转移方程是: f[i][j]=min(f[i][j],f[i-1][j+down[i]]);2.上升到这里来的状原创 2021-03-30 10:21:01 · 487 阅读 · 0 评论 -
P1564 膜拜(前缀和+区间dp)
题目传送门这道题分房间就只有三种情况:1.本房间人全部崇拜神犇12.本房间人全部崇拜神犇23.本房间的崇拜神犇1和神犇2的差值小于m的那么就可以通过一个前缀和数组来实现这个事情崇拜神犇1的+1,崇拜神犇2的-1然后再列出状态转移方程for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ //本区间的前一个区间的状态值加一 if(j满足当前条件) dp[i]=min(dp[j1]+1,dp[j2]+1,……dp[j3]+1) }}原创 2021-03-23 16:53:52 · 108 阅读 · 0 评论 -
CF1397E Monster Invaders(思维+dp)
题目传送门这道题是一个很明显的dp问题那么这道题关于读题有一个主要注意的地方:1.如果用手枪或者AWP击杀Boss之前,这一层的小怪必须已经全部杀光2.如果没有把Boss一招入魂(一下杀死),那么我们必须直接跳转到其他楼层。这道题比较复杂的一点就是状态转移很复杂。当然了,这个楼层的状态只有boss死亡和残血两种状态那么我们用dp[i][0]dp[i][0]dp[i][0]代表第iii层的boss残血,用dp[i][0]dp[i][0]dp[i][0]代表第iii层的boss死掉了,只有这两种状原创 2021-03-19 10:00:32 · 138 阅读 · 0 评论 -
UVA11584 Partitioning by Palindromes(回文子串+区间dp)
题目传送门这道题的题目大致意思是:输入一个字符串,尽可能的划分成少的字符串。分析状态分析状态分析状态:dp[i]代表前i个元素中可以划分成为几组字符串dp[i]代表前i个元素中可以划分成为几组字符串dp[i]代表前i个元素中可以划分成为几组字符串集合属性集合属性集合属性:MinMinMin那么枚举一下每一个回文字符串的最后一位,下面就是枚举一下回文字符串的最前面一位,因此有如下表达式:for(int i=1;i<=s.size();i++){//枚举末位 for(int j=1;j<原创 2021-03-12 11:53:14 · 111 阅读 · 0 评论 -
P1439 【模板】最长公共子序列(dp/lis)
题目传送门50分O(n2)TLE思路50分O(n^2)TLE思路50分O(n2)TLE思路这道题不能用二维数组来状态转移!要不然你会RE。集合表示:集合代表当前本点的公共子序列长度的最大值。属性:MaxMaxMax状态转移:dp[i][j]=Max(dp[i−1][j−1],dp[i−1][j])dp[i][j]=Max(dp[i-1][j-1],dp[i-1][j])dp[i][j]=Max(dp[i−1][j−1],dp[i−1][j])如果a[i]=a[j]a[i]=a[j]a[i]=a[原创 2021-03-10 23:38:01 · 196 阅读 · 0 评论 -
P1020 [NOIP1999 普及组] 导弹拦截 (dp/lis)
题目传送门第一问100分思路100分思路100分思路先确定集合的性质(我们用这个集合存什么东西):我们用这个集合存储什么东西?存储以这一位数字为末的最小下降子序列的位数。再来看这个集合如何计算的?集合存储的是以这一位为末尾的子序列的长度,那么我们找到这一位子序列的上一位就好,因此开二重循环,for(int i=1;i<=n;i++)//枚举以第i位为末尾 for(int j=1;j<i;j++)//如果i之前的位中有比它大的就状态转移 if(a[i]<=a[j])dp[i]原创 2021-03-10 23:23:49 · 338 阅读 · 0 评论