
DP
DP好题
_WAWA鱼_
郑州大学退役ACMer,目前在小米做浏览器内核(WebKit)开发,曾在科大讯飞实习做大模型SDK,努力成长中,欢迎大家一起学习和交流~
展开
-
F. Vitaly and Advanced Useless Algorithms---01背包求方案数
题目链接#include <iostream>#include <cstring>#include <algorithm>#include <vector>#include <array>using namespace std;#define int long longvoid solve(){ int n,m; cin>>n>>m; vector<int>lim(n); for(原创 2022-03-09 20:25:08 · 337 阅读 · 0 评论 -
[AHOI2009]CHESS 中国象棋---组合数优化状压DP
题目链接摘自:Dream_Maker_yangkai链接#include <iostream>#include <cstring>#include <algorithm>#include <vector>using namespace std;#define int long longconst int N = 110,mod = 9999973;int f[N][N][N];int C[N][N];int n,m;signed原创 2022-02-13 09:33:49 · 327 阅读 · 0 评论 -
A. Parsa‘s Humongous Tree---简单树形DP
题目链接#include <iostream>#include <cstring>#include <algorithm>#include <vector>#include <map>using namespace std;#define int long longconst int N = 200010;int e[N],ne[N],h[N],idx=0;int l[N],r[N];int n;int f[N][2];.原创 2022-02-10 11:09:53 · 410 阅读 · 0 评论 -
树形DP汇总
文章目录一、最长路径问题(1)`边`权最长路径1.树的最长路径题目链接2.点权最长路径二、有依赖的背包问题(1)点权依赖问题1.有依赖的背包问题---树形DP题目链接2.选课---超级源点优化的树形DP题目链接(2)边权依赖问题一、最长路径问题(1)边权最长路径1.树的最长路径题目链接#include <iostream>#include <cstring>#include <algorithm>using namespace std;const in原创 2022-02-08 22:14:49 · 323 阅读 · 0 评论 -
字符串DP总结
字符串DP题型复盘一、回文字符串多维度变形1.求字符串中最长回文`子序列`长度1.最长回文子序列---区间DP题目链接2.求字符串中最长回文`子串`长度1.最长回文子串---区间DP题目链接2.小A的回文串---区间DP题目链接3.无权值回文字符串最值问题1.Palindrome---LCS优化题目链接4、有权值回文字符串最值问题1.Cheapest Palindrome---区间dp题目链接5.合并回文子串1.合并回文子串---区间DP题目链接二、从原串中找子序列1.不同的子序列---DP题目链接2.Nu原创 2022-02-04 16:29:34 · 1371 阅读 · 6 评论 -
前缀和优化DP详细总结
文章目录一、连续子段和1.两段长度为k的不相交区间连续和最大值题目链接2.两段不限制长度的不相交区间连续和最大值题目链接3.m(m>2)m(m>2)m(m>2)段长度为k的不相交区间连续和最大值4.m(m>2)m(m>2)m(m>2)段不限制长度的不相交区间连续和最大值题目链接最大子矩阵---两列数中选k个子矩阵和最大(难)题目链接二、普通DP优化1.一维前缀和优化题目链接2.二维前缀和优化题目链接一、连续子段和1.两段长度为k的不相交区间连续和最大值题目链接思原创 2022-02-02 17:38:42 · 2151 阅读 · 0 评论 -
M - Candies----前缀和优化DP
题目链接TLE做法#include <iostream>using namespace std;const int N = 100010,mod=1e9+7;int f[N];//前i个人且共分了j个蛋糕 int a[110];int n,m;signed main(){ cin>>n>>m; for(int i=1;i<=n;i++)cin>>a[i]; f[0]=1; for(int i=1;i<=n;i++)原创 2022-02-02 15:13:22 · 457 阅读 · 0 评论 -
F - |LIS| = 3---多个约束条件的dp(难)
题目链接题解传送门#include <iostream>using namespace std;const int N = 1010,mod=998244353;int f[N][12][12][12];//f[i][a][b][c] 前i项的序列中长度为1,2,3的最长上升子序列中结尾最小值为a,b,c的数量 signed main(){ int n,m; cin>>n>>m; f[0][m+1][m+1][m+1]=1; for(int i=原创 2022-02-02 11:38:43 · 829 阅读 · 0 评论 -
舔狗舔到最后一无所有----简单DP
题目链接简单DP思路:因为题目要求连续三天不去同一家,所以我们只需要考虑第i-1天和i-2天情况即可状态表示:f[0/1/2][i]前i天去第0/1/2家购买方案状态计算f[0][i]=f[1][i-1]+f[2][i-1]+f[1][i-2]+f[2][i-2]f[1][i]=f[0][i-1]+f[2][i-1]+f[0][i-2]+f[2][i-2]f[2][i]=f[1][i-1]+f[0][i-1]+f[1][i-2]+f[0][i-2]#include <iost原创 2022-01-22 15:55:35 · 664 阅读 · 3 评论 -
分裂----贪心+状压DP
典型的难题短代码大佬思路传送门题解就是说,这道题先把问题转化一下,最后答案为:res=n+m-2*f[(1<<n+m)-1]状态表示sum[i]表示,当子集状态为i时,古代状态-现代状态 面积之差为多少。f[i]表示,当子集状态为i时,i最多能划分成多少两两对应和相等的子集。这个状压dp即求所有状态最多能化为多少个两两对应和相等的子集状态计算:f[i] i表示每种状态,对应位数为1时,这个数存在,为0时不存在进行状态转移,当sum=0时,f[i]++#include &l原创 2022-01-21 14:52:17 · 233 阅读 · 0 评论 -
Kingdoms-----状压dp
状态表示:f[i]=0 表示状态为i不存在f[i]=1 表示状态为i存在其中状态i 哪一个为1表示破产,0表示没破产每次用老状态更新状态计算如果旧状态可以更新的新状态,并且新状态入不敷出,则把新状态置为1,即新状态存在for(int k=0;k<n;k++) if(!(i&(1<<k)))t+=w[j][k];if(t>0)f[i|(1<<j)]=1;#include <iostream>#include <cs..原创 2022-01-21 11:16:04 · 134 阅读 · 0 评论 -
排列perm----暴力/状压dp
暴力能过,但这题本意应该不是让写暴力的,顺便学习一下状态压缩dp解法暴力写法:#include <iostream>#include <cstring>#include <algorithm>using namespace std;#define int long longchar s[12];int num[15];int n,m;signed main(){ int T; scanf("%lld",&T); while(T--..原创 2022-01-20 23:49:29 · 242 阅读 · 0 评论 -
leetcode买卖股票1-4详解----状态机+DP+思维
1.买卖股票题目链接思路:因为只买卖一次,所以对于第i天来说,找到第i天之前的最小值买入,第i天卖出即可,class Solution {public: int maxProfit(vector<int>& p) { int res=0; for(int i=0,minv=INT_MAX;i<p.size();i++) { res=max(res,p[i]-minv);原创 2022-01-15 17:49:19 · 221 阅读 · 1 评论 -
机器分配---dp+dfs
题目链接#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N = 20;int n,m;int f[N][N],w[N][N];int path[N];void dfs(int i,int j){ if(i==0)return ; for(int k=0;k<=j;k++) {原创 2022-01-14 16:24:57 · 173 阅读 · 0 评论 -
Codeforces Round #765 (Div. 2)C. Road Optimization---DP
状态表示:f[i][j] 表示 前i个站点,移走 j个车牌的最小权值状态转移:车牌可以连续移走也可以单个移走,我们枚举小于i的所有站点j,拿走j到i之间所有的车牌,可以实现状态的全覆盖,需要判断可拿走车牌的数量k要大于i-j-1状态转移方程:f[i][k]=min(f[i][k],f[j][k-(i-j-1)]+v[j]*(d[i]-d[j]))#include <iostream>#include <cstring>#include <algorithm>原创 2022-01-12 23:10:00 · 299 阅读 · 0 评论 -
AcWing第27场周赛
2.第k个数-----简单二分题目链接要找矩阵中的第k个数,暴力思想是枚举每一行,把每一行小于答案的数统计出来,因为a[i][j]=i*j 每一行都单调递增,所以可以用二分#include <iostream>using namespace std;#define int long longconst int N = 100010;int n,m,k;bool check(int mid){ int res=0; for(int i=1;i<=n;i++)原创 2021-12-11 23:06:03 · 531 阅读 · 0 评论 -
树上子链-----树上DP模板提题
题目链接树上DP重点:::一个点可以有两条链,做题时这点忘记了#include<bits/stdc++.h>using namespace std;#define int long longint n;const int N = 200010;int e[N],h[N],ne[N],w[N],idx=0;int f[N];void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++;}int res=-0x3f3原创 2021-11-30 23:50:53 · 576 阅读 · 0 评论 -
哈理工新生赛---翻转卡片---状态机DP+概率数论
新生赛出这题真可了状态表示f[i][j][0/1]表示前前i张牌选择完毕,反转了j次,第i张是反面或者正面状态转移分别对应0101 1001这两种情况f[i][j][1]+=(f[i-2][j-1][1]+f[i-3][j-1][1])f[i][j][0]+=(f[i-1][j][1])#include<iostream>#include<cstring>#include<algorithm>using namespace std;typedef l原创 2021-11-28 22:26:07 · 134 阅读 · 0 评论 -
Min酱要旅行----01背包问题变形
Min酱要旅行题目链接#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N = 2310;int v[N];int f[N],g[N];int main(){ int n,m; cin>>n>>m; for(int i=1;i<=n;i++)cin>>v[i];原创 2021-11-26 18:23:38 · 490 阅读 · 0 评论 -
[NOIP2001]统计单词个数----双重DP+字符串贪心出理
题目链接这道题写了两个DP第一个sum[i][j]预处理i到j中所含有的字符串数量从后往前判断,便于判断第i个字符是否用上写一个check函数如果第i个字符用上了x.find(a[i])==0返回true第二个dp算最大值f[i][j]表示前i个字符分为j段的最大值f[i][j]=max(f[i][j],f[k][j-1]+sum[k+1][i]) (j-1<k<i)#include <iostream>#include <cstring>#inclu原创 2021-11-26 15:20:01 · 104 阅读 · 0 评论 -
[SCOI2009]粉刷匠-----二维涂色DP问题
[SCOI2009]粉刷匠题目链接dp[i][j][k][0/1]前i条j段涂k次,最后一段涂红/蓝的最多正确格子数红(0)蓝(1)#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N = 52;int f[N][N][N*N][2];char g[N][N];//dp[i][j][k][0/1]//前i条j段涂k次,最后一原创 2021-11-26 12:18:55 · 482 阅读 · 0 评论 -
Codeforces Round #756 (Div. 3) F. ATM and Students
这题就是求最大连续子序列,并使其区间和一直大于某个数K题目链接双指针算法#include<iostream>using namespace std;#define int long longconst int N = 200010;int n,K;int a[N];signed main(){ int T,l,r; cin>>T; int s; int l1,r1; while(T--) { cin>原创 2021-11-26 08:09:07 · 442 阅读 · 0 评论 -
[NOIP2014]飞扬的小鸟
[NOIP2014]飞扬的小鸟题目链接这道题状态转移方程没什么难度,关键是细节太多了,处理起来比较麻烦#include <iostream>#include <cstring>#include <algorithm>using namespace std;#define x first#define y secondtypedef pair<int,int>PII;const int N = 10010,M=1010,INF=0x3f3f3原创 2021-11-25 17:03:39 · 102 阅读 · 0 评论 -
[USACO 2016 Ope P]262144----基于倍增思想的DP问题,真是米奇妙妙屋,妙到家了
[USACO 2016 Ope P]262144题目链接f[i][j]表示凑出i的且左边界为j(闭区间)的右区间(开区间)好像并查集如果左边界为j时凑出i的右边界为0则i-1的右边界变成左边界,再找一个可以凑出i-1的右边界,就能凑出i了即f[i][j]=f[i-1][f[i-1][j]]如果能凑出i则答案更新一下就好了#include<iostream>#include<cstring>#include<algorithm>using namesp原创 2021-11-24 21:51:43 · 444 阅读 · 0 评论 -
Fox And Jumping----裴蜀定理+DP
Fox And Jumping题目链接题意是花最小的价值选几个数,使这几个数可以组成任意数根据裴蜀定理即让这几个数最大gcd为1状态表示:f[i]表示最大公约数为i得最小花费然后暴力就行了#include <iostream>#include <cstring>#include <algorithm>#include <map>using namespace std;const int N = 310;int n;map<int原创 2021-11-24 19:34:23 · 286 阅读 · 0 评论 -
[NOIP2005]过河----简单DP+数学公式+离散化处理
[NOIP2005]过河题目链接状态表示:f[i]表示前i步且在i这个位置所跳过的最小石子个数状态转移方程:如果i位置有石子f[i]=min(f[i-j]+1,f[i])否则f[i]=min(f[i-j],f[i])这题状态转移方程很简单,关键是路程范围1e9太大了,必须离散化离散化之前需要知道一个数学定理:对于本题来说就是:当两个石子距离超过st时 st后的任意距离都可以到达证明:这个数学定理有什么用呢,就是说当两个石子距离超过st时,之前的所有状态都可以转移到i的位置,所以走了原创 2021-11-24 15:18:49 · 239 阅读 · 0 评论 -
前缀和DP总结
To the Max题目链接暴力做法预处理二维前缀和,枚举矩阵的左上角和右下角两个位置,计算中间最大值复杂度O(n^4)#include <iostream>#include <algorithm>using namespace std;typedef long long ll;const int N=105;const int inf=0x3f3f3f3f;int a[N][N] , b[N][N] ;int main(){ int n ;原创 2021-11-23 21:19:27 · 158 阅读 · 0 评论 -
[USACO 2009 Dec G]Video Game Troubles-----分组背包的改良版
这题是分组背包的改良版,如果还按分组背包的思路枚举每组物品状态会TLE因此需要换一种思考方式类似于状态机模型状态表示f[i]表示前i-1里任意选,但是选第i个物品的最大价值g[i]表示前i个物品里边任意选的最大价值每次弄人f[i]里边放了第i个物品,把物品的分组跑一边01背包然后用来更新g[i]这里的f[i]起到工具人的作用状态转移方程:f[j]=max(f[j],f[j-v]+w)g[j]=max(g[j],f[j-price])#include<iostream>#i原创 2021-11-23 19:20:57 · 358 阅读 · 0 评论 -
简单瞎搞题-----bitset简单状态DP
题目链接这题数据范围比较小,直接暴力转移就好了这里复习一下bitset可以减小空间每一位代表能转化的那个数状态表示f[i]是bitsetf[i]表示,在前i层里边,f[i]中数为1的位代表可以转化为这个数状态转移方程f[i]|=(f[i-1]<<(j*j))#include<iostream>#include<bitset>using namespace std;const int N = 1000010;bitset<N>f[105原创 2021-11-23 12:40:42 · 106 阅读 · 0 评论 -
迁徙过程中的河流----贪心+思维dp
迁徙过程中的河流题目链接f[i]表示前i个人已经滑到对面的最小时间根据贪心思路先从小到大排序f[1]=w[1] ······第一个人滑到对岸时间f[2]=w[2] ······前两个人一块滑到对岸时间然后状态转移f[i]=min(f[i-1]+w[1]+w[i],f[i-2]+w[1]+w[i]+2*w[2])#include<iostream>#include<cstring>#include<algorithm>using names原创 2021-11-23 12:17:37 · 556 阅读 · 0 评论 -
钉子和小球-----简单线性dp
钉子和小球-----简单线性dp题目链接最后一行的格子想起来比较麻烦,统一的把格子看成钉子,就比较好解决了状态表示:f[i][j]表示第i行第j列落到这个钉子上球的个数状态转移方程分两种情况:1.有钉子存在f[i+1][j]+=f[i][j]f[i+1][j+1]+=f[i][j]2.无钉子存在f[i+2][j+1]+=4*f[i][j]这里小球在i+1层直线下落,这里必须要乘以4,因为这是模拟的小球下落过程的每一种情况,每下落一层小球会分裂为2个,第i+1层的两个球分裂为四个都是直原创 2021-11-21 10:18:00 · 171 阅读 · 0 评论 -
wyh的问题-----状态机+区间dp
wyh的问题-----状态机+区间dp题目链接这题感觉算是比较难的区间dp问题了,难点在于看起来像区间dp,但是状态太多,找不到状态转移方程,对于每一个位置可以由右边走过来也可以由左边走过来,因此状态表示为f[i][j][0]表示i到j已经走过且最后位置在i的最小花费f[i][j][1]表示i到j已经走过且最后位置在j的最小花费走的时候时间是一直在走的,所以需要用前缀和把每个区段没关的灯的速率累加起来乘以时间顾可得状态转移方程为f[i][j][0]=min(f[i+1][j][0]+(d[i+原创 2021-11-21 09:09:38 · 871 阅读 · 1 评论 -
取数游戏2----区间DP逆向四维
取数游戏2----区间DP逆向四维题目链接正向思维来想的话会发现a数组只能去第一个和最后一个很难找到状态如何转移,逆向来想,最后一个a元素可以是任何一个位置,倒是第二个是a的左边或者右边,理所应当想到用区间dp来写了因为逆向,所以开始要乘以b[n]状态转移方程:i=j时即len=1f[i][j]=b[n]*a[i]否则f[i][j]=max(f[i+1][j]+b[n-len+1] * a[i],f[i][j-1]+b[n-len+1] * a[j])#include<iostrea原创 2021-11-20 23:16:11 · 2912 阅读 · 0 评论 -
Music Problem----任意区间和等于n的倍数的dp问题
题目链接解一:由鸽巢原理,一个由n个数组成的数列 一定能找出若干个连续的数使它们之和能被n整除所以直接剪枝,大于3600输出YESf[i][j]表示前i个数余数为j的个数状态转移方程:f[i][j]|=f[i-1][j]f[i][(j+a[i])%3600]|=f[i-1][j]#include <iostream>#include <string.h>using namespace std;int a[100010];int f[3610][3610];v原创 2021-11-20 12:52:15 · 318 阅读 · 0 评论 -
失衡天平-----思维+dp
失衡天平-----思维+dp题目链接这道题题意是个坑,不是随意取任意多次,不然解不出来,因为任意两堆重量相差m的物品合到一块重量相差一定还是小于m,所以这道题的问题转化为将n个物品分成3组,分别是 加到左边,不选,加到右边三种情况,算这三种情况的最大值f[i][j]表示前i个物品,左边比右边重量多j的最大重量f[i][j]可由三种状态转移过来分别是第i个物品放左边:f[i-1][j-w]+w这里需要注意的是j-w小于0的话相当于右边比左边多j-w,左边和右边可以互换,等价于左边比右边多j-w,顾原创 2021-11-20 10:10:33 · 274 阅读 · 2 评论 -
传球游戏-----环形DP
题目链接思路:f[i][j]表示传了i次,且第i次在第j个小朋友手里的方案数每个状态只能由左右两个小朋友转移而来顾状态转移方程为:f[i][j]=f[i-1][(j-1+n)%n]+f[i-1][(j+1)%n]#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N = 40;int f[N][N];int n,m;int mai原创 2021-11-18 19:26:36 · 2056 阅读 · 0 评论 -
免费馅饼-----线性DP
一道dp一下午。。。。免费馅饼题目链接高度为H,从第一格开始降落,第一格不算,所以首先H--当馅饼在某一秒末恰好到达游戏者所在的格子中,游戏者就收集到了这块馅饼。注意恰好这个词,所以当H不能整除速度v时,数据没用,读入数据时需要特判去除不能整除v的数据。把每个饼落到第一行的总时间记录下来,进行dp运算这道题有五个状态转移,因为要输出移动方案,所以时间倒着来写,最后输出中间位置的最大值f[0][W/2+1]f[i][j]表示前is内,第j个位置的最大值f[i][j]可由f[i+1][j+2]原创 2021-11-18 16:48:49 · 2649 阅读 · 0 评论 -
花店橱窗-----线性DP
这题写了整整一晚上,呜呜呜呜~,太菜了。。。。dp dp dp dp dp dp dp dp dp dp dp dp dp dp dp dp dp dp dp dp dp dp dp dp花店橱窗题目链接解一:f[i][j]表示前i朵花里边选且,第i朵花放在 第j个花瓶的最大值状态转移方程:f[i][j]=max(f[i-1][1],f[i-1][2],.....f[i-1][k],....f[i-1][j-1])+w[i][j](其中k<j)同时要求本题输出最大路径:用p[i][j]原创 2021-11-18 13:22:01 · 227 阅读 · 0 评论 -
可爱の星空-----简单线性DP
开始大概看一下数据范围1e12,就觉得这是一个思维题,结果一直WA,又被题骗了,没想到这是一个线性dp题。好像区间dp但又不是,竟然二分来写了。题目链接记忆化搜索+递推#include<bits/stdc++.h>using namespace std;#define int long longconst int N=100010,mod=1e9+7;int f[N];map<int,int>S;void init(){ for(int i=2;i<原创 2021-11-17 18:04:06 · 581 阅读 · 1 评论 -
最长公共上升子序列----LIS+LCS
最长公共上升子序列题目链接#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N = 3005;int n;int a[N],b[N];int f[N][N];int main(){ cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; for(int原创 2021-11-07 22:43:39 · 87 阅读 · 0 评论