
动态规划
常见DP
谁是凶手1703
这个作者很懒,什么都没留下…
展开
-
巡逻【树的直径】【树形dp】【bfs】
题目传送门在最初的树上,求出树的直径L1 然后将这条路径上的所有边权统统取反.1变成−1我们再求一次树的直径L2L2.答案就是2×(n−1)−(L1−1)−(L2−1)=2×(n−1)−L1+1−L2+1假如说L2L2和L1L1有重叠部分.那么当我们−L1+1的时候,我们就会发现,重叠的部分变成了只需要经过一次.然后−L2+1−L2+1相当于把重叠部分相加回来了....原创 2019-08-31 08:51:06 · 117 阅读 · 0 评论 -
方格取数【三维dp】
题目传送门题意:给出一个矩形 , 从左上走到右下 , 走俩条路线模型:二维dp记录一条路线f[i1,j1,i2,j2] 表示从(1,1)(1,1) 走到(i1,j1) (i2,j2) 的最大值当i1+j1 = i2+j2 时 俩条路径的格子才重合状态表示 k=i1+j1 f[k][i1][i2] 表示走k步 俩条线的位置;#include<bits/stdc++.h...原创 2019-10-27 10:22:11 · 326 阅读 · 0 评论 -
最长公共上升子序列【优化】
给俩个序列,求最长公共上升子序列;状态表示:f[i][j] : 1到i 和1到 j 以b【j】结尾的序列集合属性 max状态转移方程:分为有没有a【i】】的集合若无a【i】则f[i][j] =f[i-1][j];若有a【i】前提a【i】 == b【j】 ,则for(int k=1;k<j;k++){ if(b[k]<a[i]) f[i][j]=max(f[i][j],f...原创 2019-12-25 22:06:44 · 186 阅读 · 0 评论 -
k-Amazing Numbers(思维)
k-Amazing Numbers(思维)思路数组a[n] 中,k从1到n。求出序列:a[1 – k], a[2 – k+1] , a[3 – k+2],都出现的数的最小值。设x都出现在这些区间,那么这些x之间的位置差最大d[x] <k,第一个x的位置<=k,最后一个x的位置>=n+1-k.d[x] = k:x需要的k值 , 那么k,k+1,k+2-- n的值都是x,定义f[] 记录k k+1 k+2。-- n#include <bits/stdc++.h>us原创 2020-11-01 18:09:21 · 170 阅读 · 0 评论 -
修剪草坪【单调队列DP】【f(i)前i个合法序列的最大值】
思路思路1长度为m+1的序列必须不选择1个的最大值反过来想,长度为m+1的序列中至少选择一个,选出来最小值,然后总和处理f[i] :前i个序列最后一个序列选的最小值转移:在i前面的m+1个f[i] 中选择最小的 + a[i]长度为m+1中f[i] 的最小值,单调队列优话思路2定义状态f[i] :前i个序列中合法的序列最大值第i个数选、不选不选:f[i-1]选选上这个点+之前的连续选点长度为1<=x<=m转移:f[i-x-1] + a[.原创 2020-11-11 19:40:12 · 135 阅读 · 0 评论 -
动态规划小总结
计数问题题意 :0-n之间有多少个k思路 例如求:abcdefg中k的个数枚举带第d时候abc d efg中k的数开始分类讨论,拿abc说事000-abc-1 d 000-efgabc固定d<k 0d==k. 000-efgd>k 000-999怎么处理前导0,前导0的出现:k=0时才会影响以上步骤如果k==0,枚举的时候从次高位枚举,不会出现00了此外,分类时候,000-abc-1 d 000-efg这种情况,d==0,000-abc原创 2020-08-14 10:24:50 · 129 阅读 · 0 评论 -
绿色通道【二分】【单调队列优化DP】【序列中连续m不选】【序列中每m+1个选择一个】
绿色通道题意长度为n的序列,可以选择最长长度为len的空序列,保证剩下的序列能在T时间内完成。他最长的空题段len至少有多长就可以了思路首先,最长的空题段len:序列中len+1长度内选择1个,check出可以不可以。然后,要求这个len最少,二分模板中右半部分为true,左半部分为false,进行二分。考虑cheak函数序列中len+1中选择1个f[i] :序列中前i个序列,第i个位置选择的价值转移,i前面len+1个位置中最小的f[i] + a[i]用单调队列优化一下。把最小值从原创 2020-11-12 11:24:52 · 137 阅读 · 0 评论 -
树形DP总结【acwing提高课】
树的最长路径思路基本想法就是dfs求出子树的最大高度基于这个求出最大高度、次大高度代码#include<bits/stdc++.h>using namespace std;const int N=2e4+100;int h[N],ne[N],w[N],e[N],idx;void add(int a,int b,int c){ e[idx]=b; ne[idx]=h[a]; w[idx]=c; h[a]=idx++;}int n,m;int原创 2020-08-23 17:12:02 · 412 阅读 · 0 评论 -
旅行问题【单调队列优化DP】【顺时针变前缀和、逆时针变后缀和】【下标+1、-1】
旅行问题环形:2倍空间处理判断中间有没有油:油的前缀和 - 路程的前缀和顺时针,前缀和。逆时针,后缀和顺时针处理:要从后往前枚举:维护的单调队列长度为:n+1因为是前缀和,我们用i后面n个元素的最小值和i比较比较成功之后,i+1为true刚开始q[0] 放下标2*n+1逆时针处理(同理,注意下标)#include<iostream>#include<algorithm>using namespace std;const int N=2e6+100;原创 2020-11-12 10:33:13 · 147 阅读 · 0 评论 -
饼干【贪心确定序列】【类似整数划分DP】【记录中间状态,递归输出路径】
饼干n个孩子,m个饼干。每个孩子都有一个嫉妒值,嫉妒值=(有多少个孩子的饼干比他多)* g。求一种分配方式,使得总体嫉妒值最小思路先处理嫉妒值:贪心,处理每个孩子的顺序,使得分配的饼干数量单调下降。贪心流程:g值越大,多分配饼干,然后把孩子编号排序。排好序之后的题目:n个孩子,m个饼干的嫉妒最小值,并且这斜孩子的饼干数单调下降。类似整数划分的思想f[i] [j] : 前i个孩子,分配了j块饼干的情况状态转移:第i个孩子以及之前的孩子,那段区间都是1块饼干的个数考虑输出路径:输出路原创 2020-11-21 12:42:26 · 665 阅读 · 2 评论 -
Unmerge( 序列拆分成小序列+,然后01背包 )
Unmerge( 找规律 + 01背包 )题意给出一个序列,把这个序列拆成俩个序列,这俩个序列每次取最前面的最小值,构成一个新序列,这个新序列是不是原来的序列。思路每个取俩个序列front的最小值。3 2 6 1 5 7 8 4,那么3 2 必定在一个序列、并且相邻若不在一个序列,那先输出2 然后 3若不相邻,那输出3之后,就不会输出2基于以上规律,拆分成若干小的序列。我们从这些小序列中选择出几个,看能不能构成俩个子序列中的一个。可以的话,输出yes这个过程就是01背包#incl原创 2020-11-06 14:48:25 · 248 阅读 · 0 评论 -
扑克牌【概率DP】【状态表示:每种类有多少个】
概率DP要抽象出:起点、中点转移的时候:一个点转移到n个点,然后记忆化题目Admin生日那天,Rainbow来找Admin玩扑克牌。玩着玩着Rainbow觉得太没意思了,于是决定给Admin一个考验。Rainbow把一副扑克牌(54张)随机洗开,倒扣着放成一摞。然后Admin从上往下依次翻开每张牌,每翻开一张黑桃、红桃、梅花或者方块,就把它放到对应花色的堆里去。Rainbow想问问Admin,得到A张黑桃、B张红桃、C张梅花、D张方块需要翻开的牌的张数的期望值E是多少?特殊地,如果翻开的牌原创 2020-11-10 20:21:03 · 475 阅读 · 0 评论 -
D. Rarity and New Dress【DP】【以一个点向上延伸的最长边长为DP】
D. Rarity and New Dress题意给出一个矩阵,求一下矩阵中类似图中斜方体的个数。思路DP:f[i] [j] :表示(i , j)这个位置,往上可以延伸的最大斜方体的边长(不是高度)那么f(i,j) = x就可以组合出来x种斜方体。关于f(i,j) 的推导:f(i,j) 恰好是:(i-1,j-1) 、(i-1,j+1 ) 、(i,j-2) 这三个点的最小值。转移条件为:那四个点一样,代码#include<iostream>#include<algori原创 2020-11-05 15:28:57 · 159 阅读 · 0 评论 -
最优包含【最短编辑距离类的DP】
最优包含我们称一个字符串 SS 包含字符串 TT 是指 TT 是 SS 的一个子序列,即可以从字符串 SS 中抽出若干个字符,它们按原来的顺序组合成一个新的字符串与 TT 完全一样。给定两个字符串 SS 和 TT,请问最少修改 SS 中的多少个字符,能使 SS 包含 TT?输入格式输入两行,每行一个字符串。第一行的字符串为 SS,第二行的字符串为 TT。两个字符串均非空而且只包含大写英文字母。输出格式输出一个整数,表示答案。数据范围1≤|T|≤|S|≤10001≤|T|≤|S|≤1000原创 2020-11-02 20:37:47 · 867 阅读 · 1 评论 -
守卫者的挑战【概率DP】【处理内存、偏移量】
守卫者的挑战题意n项挑战,每项挑战,有获胜的概率,每项挑战的收益有正数、-1.问这n项挑战中,获胜l场以上,并且收益为>=0的概率。思路n个物品中选择>=k个,01背包的思路,然后有物品的个数限制,多加一维度表示拿了几个物品,有收益的限制,再多加一维。因此状态表示为:f[i] [j] [k] :前i项挑战,获胜j场,收益为k的概率。题意要求,转移过程中可以有负数,意味着收益可以为 负数。题目要求我们求最后收益>=0的概率,因此我们把一定收益>=0的收益概率压缩到收益为n(为原创 2020-10-27 22:16:19 · 291 阅读 · 0 评论 -
鸣人的影分身【按照前i个数,最小数是不是0,建立转移方程】
鸣人的影分身题意鸣人最多有n个分身,m的能量。分身的能量可以为0.问有多少种方案数。思路很容易定义状态:f[i] [j]: 前i个分身,共花费能量j的方案数。状态转移:刚开始想的枚举第i个能量是多少,根据这个建立方程,这个是错的,因为题目的一种方案不考虑前后顺序。这个转移很巧妙,根据这i个分身能量的最小值是不是0,划分为俩类:是0的话,那可以把这个0分身去掉:f[i-1] [j];不是0的话,那其他能量>=1,我们把这些数都-1,那这些分身就有>=0,状态为:f[i] [j-原创 2020-10-14 23:42:23 · 117 阅读 · 0 评论 -
陪审团【01背包】【输出路径】
题意n个人选m个人,每个人有p[i],d[i]的值,要选出这m个人的所有(p值和)-(d值和)最小,并且p值和+d值和最大。并且输出方案。思路组合最优化问题,背包问题。p-d最小,把这个约束定为一维度,选择m个数,把这一约束定为一维度。f[i] [j] [k] : 前i个数,选了j个数,p与d的差值为k,的和值最大。因为我们要输出路径,不能滚动数组优化,另外要把负值外加偏移量。要保证j的维度决定值最小,要判断这个值的正负。代码#include<cstdio>#include原创 2020-10-12 21:15:47 · 134 阅读 · 0 评论 -
倍数问题【组合问题的最优化,背包问题】【余数相同,保证和最大,筛选出余数相同的几个最大值】
倍数问题题意给n个数,从里面选择3个数,保证这三个数和是K的倍数,选出和最大的一组数,输出这个和。题解背包问题的核心:一堆物品的组合问题的最优解。这个题也是:组合问题的最优解。这个问题的约束:有三个数、是K个倍数。K的倍数一般用模的余数来表示。我们可以定义f[i] [j] [k] :表示前i个数,选择j个数,除K的模下余数为k的最大和,因为这个本质上:一堆物品的组合问题,就是背包问题,我们可以把这个优化掉一维。接下来考虑和最大的问题:余数相同,和最大。我们可以把余数相同的数放在一起,取值最大原创 2020-10-11 16:53:50 · 599 阅读 · 0 评论 -
掷骰子【普通线性DP】【转移方程可以优化为矩阵快速幂】
掷骰子思路可以先定义一个状态f[i] [j]: 前i个骰子,最后一个面是j的方法数,肯定超时,然鹅可以混一些分,代码如下 for(int i=1;i<=6;i++) f[0][i]=1; for(int i=1;i<=n;i++) { for(int j=1;j<=6;j++) { for(int k=1;k<=6;k++) { int _ops=原创 2020-10-11 14:15:14 · 193 阅读 · 0 评论 -
移动服务(f[i] [j] [k],这三个人,位置为a[i],j,k的最小价值)
移动服务(f[i] [j] [k],这三个人,位置为a[i],j,k的最小价值)题意给出点之间到达价值,使用3个人处理一个序列,f[i] [j] [k],这三个人,每次处理序列中一个值,三个人中一个要到这个点。三个人不能重复到达一个点。思路状态表示:f[i] [a] [b] [c]:表示:处理到第i个序列中的数,这三个人位置分别在a,b,c时的最小花费。这个状态有三种去向:a去下一个位置b去下一个位置c去下一个位置像重复覆盖问题一样,拿前面的状态更新后面的状态。注意这三个点不能一样。原创 2020-10-10 10:10:24 · 165 阅读 · 0 评论 -
分级【构造新序列,使得单调序列与原序列差值的绝对值最小】【先排序,在DP】
分级题意思路先处理单调递增的情况:构造一个新序列b,使得abs(b[i]-a[i]) 和最小。结论为:b序列为a序列中排好序的组合。即:先把a序列排序,然后a序列中课重复按照顺序组成b序列。这些序列取最小值。定义f[i] [j]: 构造的b序列中前i 个,并且最后一个为a[j]的序列状态转移:可以枚举b序列的前i-1个,最后一个为aj之前的数。这里三重循环,然后可以拿前缀和优化为二重循环。这是单调递增的情况,其中每个点在a序列中。单调递减的情况,就是把横轴翻转一下,然后求递增。代码原创 2020-10-09 19:11:22 · 266 阅读 · 0 评论 -
整数拼接【维度为10的k次方,模数的DP】【蓝桥杯】
整数拼接题意给n个整数,从里面选俩个整数,一前一后拼接成一个新数,若这个新数是k的倍数,那么res++。问res多少?思路首先暴力代码for (int i = 0; i < n; i ++ ) for (int j = 0; j < n; j ++ ) if (check(a[i], a[j])) ans ++ ;第一重循环,去不了的情况下,我们试图优化第二重循环。第二重循环,求的是:拼接结果a[i] 在前a[j]在后是k的倍数的个原创 2020-10-09 13:50:29 · 267 阅读 · 0 评论 -
杨老师的照相排列【矩阵左上角最大的线性DP】
杨老师的照相排列题意思路这些排列具有这些性质:越靠左上角越小,并且上面的数字个数比下面的多或者等于。这样我们可以想象,每次小到大放数,每次放的位置,就那么几个情况:然后DP[i] [j] [k] [l] [m] 表示这1行有i个数,第2行有j个数。。 。每次转移,要保证,上一行比这一行>=.另外,外面转移时候,“放这个位置”要保证这个行原本就有数。代码#pragma comment(linker, "/STACK:1024000000,1024000000")#include原创 2020-10-09 09:45:53 · 161 阅读 · 0 评论 -
旅游规划【树中节点往向上最长、向下最长、向下次长路径】
旅游规划题意思路求树中每个节点是不是经过树中的最长路径需要求出每个节点往下走的最长路径、往下走的次长路径、往上走的最长路径。这三个属性值可以确定:经过这个点的树中最长路径。然后比较一下,树的直径。最后输出代码#pragma comment(linker, "/STACK:1024000000,1024000000")#include<cstdio>#include<cstring>#include<algorithm>#include<i原创 2020-10-08 19:06:03 · 171 阅读 · 0 评论 -
括号配对【区间DP】【回文子串】
括号配对题意递归定义一组字符匹配模式增加几个字符满足这个匹配。思路添加多少个字符,可以转化为n-“回文子串”,这里的回文子串需要重新定义AAAABBBB:A符合定义,B也符合定义的话:最长子串,我们枚举中间端点取最大值。ABBA:这种情况,我们判断【l, r】 match(l,r)是不是匹配,匹配的话f(l+1,r-1)+2代码#pragma comment(linker, "/STACK:1024000000,1024000000")#include<cstdio>#i原创 2020-10-08 13:10:54 · 163 阅读 · 0 评论 -
糖果(重复覆盖问题)【蓝桥杯】
糖果(重复覆盖问题)题意思路可以转化为简单的重复覆盖问题,我们用简单的状态压缩写代码#pragma comment(linker, "/STACK:1024000000,1024000000")#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string>#include<vector>#include原创 2020-10-07 12:30:20 · 283 阅读 · 0 评论 -
设计密码【状态机】【KMP】
设计密码题意求不包含子串的方案数思路匹配子串的过程就是KMP的过程,KMP不跳到m就说明,不包含这个串,状态表示:f[i] [j] :第i个位置,跳到j的方案数状态转移: 第i个位置,枚举字符,KMP找到下一个字符以及位置j代码#include<bits/stdc++.h>using namespace std;const int N=200;int f[N][N];char s[N],p[N];int n,m;int ne[N];const int mod=1e原创 2020-08-22 08:52:40 · 197 阅读 · 0 评论 -
【SCOI2009】粉刷匠
共n行,刷t次,求最大价值分组背包的性质每一行看成一组,每组刷的次数看为一组背包分组背包优化,可以边读边背包,一行一行考虑每一行,要求出刷了n次的最大价值,可以用一个dp求,定义f[i][j] : 考虑到第i个,一共刷了j次的最大价值由于是连续刷,一段一段的,在状态转移的时候,需要枚举上一段的起点k,那么起点k到i,之间的价值,可以用前缀和优化,刷出1的价值 == 区间和,刷出0的价...原创 2020-04-04 22:33:39 · 255 阅读 · 0 评论 -
猫狗大战【计蒜客】
状态表示:f[i][j] : 用i个数能不能填体积为j枚举状态 : 从大到小枚举,从小到大=完全背包了,物品是有限的,所以从小到大枚举状态转移 : f[i][j] |= f[I-1][j-v]#include<iostream>#include<cmath>#include<cstring>#include<algorithm>#...原创 2020-04-04 11:42:55 · 317 阅读 · 0 评论 -
新年趣事之打牌【01背包】【输出方案】
01背包求方案数 + 输出方案#include<iostream>#include <algorithm>#include <string.h>using namespace std;const int N=1e5;int f[107][N];int v[N];int n,m;int main(){ cin>>m>...原创 2020-04-02 20:58:53 · 342 阅读 · 0 评论 -
最长对称子串【DP】
求最长对称子串长度f[l][r] = 1 表示 l - - - r 之间是对称的#include<iostream>#include <string.h>#include <algorithm>#include <string>#include <cmath>using namespace std;const int ...原创 2020-03-24 17:13:25 · 224 阅读 · 0 评论 -
【CodeForces 1262F1 --- Wrong Answer on test 233 [Easy Version]】DP
状态表示f[I][j]: 考虑到第i 并且收益为j 的方案数收益是指: 移动后比移动前不同的数是多少收益可以为负数,下标整体偏移2000 // 最大情况就是2000初使化f【0】【0】=1状态转移* 当a[I]==a[I+1] ,考虑第i个字符 k 个字符都可以,收益不变* 其他情况 :f[i][j] ,是有哪些状态转移过来的,首先 考虑第i个字符时,代价可以+1(填a[i+1...原创 2020-03-07 15:04:11 · 186 阅读 · 0 评论 -
设计密码【状态机模型+KMP】
题意代码#include <cstring>#include <iostream>#include <algorithm>#include <string>using namespace std;const int N=55,mod=1e9+7;;int ne[N];//KMP中的next数组char str[N];//子串i...原创 2020-03-02 18:45:14 · 266 阅读 · 0 评论 -
能量石头【01背包】【贪心】【Google Kickstart2019】
题意:导图代码#include<bits/stdc++.h>using namespace std;const int N=1e5;struct node{ int s,e,l; bool operator<(const node & t)const{ return s*t.l<t.s*l; }};node...原创 2020-03-01 16:57:07 · 165 阅读 · 0 评论 -
最小支配集【皇宫看守】
皇宫看守 最小支配集链接:链接题意给一颗树,最小支配集思路和没有上司的舞会有区别,没有上司的舞会是一条边相邻的俩个点至少选一个点属于最小点覆盖最小点覆盖需要考虑 父节点,子节点,本身节点的状态f[u][0] 表示u节点被父节点的看到的最小花费f[u][1] 表示u节点被子节点看到的最小花费f[u][2] 表示u节点自己被放置的最小花费f[u][0] += sigma m...原创 2020-01-31 23:27:42 · 184 阅读 · 0 评论 -
没有上司的舞会+战略游戏【树形dp】
没有上司的舞会链接:链接题意:一颗树,点上有权值,一条边最多选一个点,求最大权重代码#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int N = 6010;int n;int h[N], e[N], ne[N], ...原创 2020-01-31 17:47:58 · 150 阅读 · 0 评论 -
苹果二叉树 有依赖的分组背包
苹果二叉树 分组背包链接思路有依赖性的分组背包树形dpf[u][j] 根节点是u,边是j的最大值分组背包:枚举组,枚举体积,枚举决策代码#include<iostream>#include<string.h>#include<algorithm>using namespace std;const int N=2e5;int e[N]...原创 2020-01-31 15:59:58 · 190 阅读 · 0 评论 -
数字转换 树的最长链
数字转换 树的最长链链接:https://www.acwing.com/activity/content/problem/content/1304/1/题意:如果一个数 x 的约数之和 y(不包括他本身)比他本身小,那么 x 可以变成 y,y 也可以变成 x。例如,4 可以变为 3,1 可以变为 7。限定所有数字变换在不超过 n 的正整数范围内进行,求不断进行数字变换且不出现重复数字的最...原创 2020-01-31 14:30:03 · 388 阅读 · 0 评论 -
树的中心
树的中心题意找到一个点使最远的点最小思路画出一颗树,找到一个点,这个点的最远距离,有俩种,一种是往下走,另外一种是往上走,往上走还有俩种,一种是再往上走另外一种是往下走,因此,我们需要,dfs出每个点到叶子节点的最大值,再dfs出每个点往上走的最大值代码#include<iostream>#include<string.h>#include<...原创 2020-01-30 23:03:32 · 262 阅读 · 0 评论 -
混合背包【01,完全,多重】
题目链接01背包,完全背包,多重背包的二进制优化#include <iostream>#include<string.h>#include<algorithm>using namespace std;const int N=1e6;int f[N],n,m;int v[N],w[N];int main(){ cin>>...原创 2020-01-21 09:33:33 · 116 阅读 · 0 评论