![](https://img-blog.csdnimg.cn/20201014180756925.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
ACM-dp
文章平均质量分 76
但求-_-心安
充满鲜花的世界到底在那里,如果他真的存在那么我一定会去。
展开
-
CCF 有趣的数
问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次。 2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前。 3. 最高位数字不为0。 因此,符合我们定义的最小的有趣的数是2013。除此以外,4位的有趣的数还有两个:2031和2301。 请计算恰好有n位的有趣的数的个数。由于答案可能非常大,只...原创 2018-12-31 09:19:32 · 260 阅读 · 0 评论 -
51nod 1354 选数字 (01背包变形)
dp5级题,是一个背包的变形题,我想把它放在五级题的原因就是很难想到这只是一个背包题吧。用map处理一下,和离散化的作用是一样的。只是用了系统自带的函数库而已。#include #define ll long longusing namespace std;const int maxn=1010,mod=1e9+7;int a[maxn];maptemp1,temp2;map::i原创 2017-10-07 19:44:43 · 256 阅读 · 0 评论 -
51nod 1378 夹克老爷的愤怒(树形dp)
树形DP,贪心思想,从叶子节点向上,能不放就不放,到了k长就放一个。后序遍历,记录不同子树上传的状态,子树状态记录为该子树可以向上管理的(缺少的用负数)可能A子树放置的家丁可以把B子树的村庄全部覆盖,这样就可以节约家丁数了。min_length = min(dp[child])max_length = max(dp[child])if(min_length ++re原创 2017-10-07 15:34:38 · 308 阅读 · 0 评论 -
Codeforces Round #439 (Div. 2)C. The Intriguing Obsession (组合数详解)
首先题意:是如果两个相同颜色的桥能相互到达他们之间的最短距离至少为3。我们去想所有的桥两两组合数量的乘积就是答案。很难证明,因为我不会证明,但是那实际的例子画一画,能发现他的正确性。乘积不会有错误的情况出现,而且能包含所有情况。下面就是两两组合的数量应该怎么算,令xdp[x-1][y-1],所以dp[x-1][y-1]*y,如果第x个小球不放入盒子中。下一步就是dp[x-1][y]。所以状原创 2017-10-07 13:55:11 · 300 阅读 · 0 评论 -
51nod 1202 子序列个数(字符串计数)
dp[i]代表是以i位的a[i]结尾,有多少种,(包括空集)状态转移方程 1.如果a[i]之前没有出现过dp[i]=2*dp[i-1] 前面i-1有dp[i-1]种可能,第i个数放或不放 2.如果a[i]之前出现过:dp[i]=2*dp[i-1]-dp[mark[a[i]]-1] 减去重复的部分,mark【i】是a[i]最近一次原创 2017-09-03 16:49:44 · 583 阅读 · 0 评论 -
51nod 1086 背包问题V2 (巧妙dp,二进制)
这里可以用多重背包拆成01背包求解的思想,不过在拆的时候不能将Cn拆成1+1+1+1+1+1.....+1的形式。这么做会超时。应该将Cn拆成 Cn=1+2+4+8+...+(Cn-sum)。 如果能理解完全背包就能理解这个,完全背包将Cn拆成1+1+1+1+1+1.....+1的形式的时候是每次放一个a【i】包,或者不放。最多就是cn,拆分成1+2+4+8+...+(Cn-su原创 2017-09-03 13:41:42 · 231 阅读 · 0 评论 -
51nod 1270 数组的最大代价
a数组的每个值取1或者b[i],所以dp【2】【maxn】就可以了#include using namespace std;int n;int a[50005];int dp[2][5005];int main(){scanf("%d",&n);scanf("%d",&a[1]);dp[1][0]=0;dp[0][1]=0;for(int i=2;i<=n;i++)原创 2017-09-03 11:19:30 · 208 阅读 · 0 评论 -
51nod 1043 幸运号码 (数位dp)
dp[i][j]表示 i 个数和为 j 的总数(包含0开头情况)dp[i][j] = dp[i-1][j-k]i & 1 :这里用滚动数组节省内存非0开头的情况 * 0开头的情况:(dp[n&1][i]-dp[(n-1)&1][i]) *dp[n&1][i],最后将其累加即为结果。开始没有想到这么做,还傻傻的dfs,用dp[1000][10]记录,今天心情不好,超级原创 2017-09-02 20:06:43 · 321 阅读 · 0 评论 -
51Nod-1412-AVL树的种类(树形dp)
状态转移方程1、dp[i][k] += dp[i - 1 - j][k - 1] * dp[j][k - 1] 2、dp[i][k] += 2 * dp[i - 1 - j][k - 2] * dp[j][k - 1]51nod评测机是window系统,要用%I64d#includeusing namespace std;typedef long long ll;#def原创 2017-09-02 17:57:58 · 277 阅读 · 0 评论 -
2017 ACM/ICPC Asia Regional Qingdao Online 1007 hdu 6212 Zuma (区间dp)
区间dp都是些智商题,首先我没看出来这是一个区间dp,因为我没去想怎么去得到他的各种状态,想不到,看了其他博主的http://blog.csdn.net/zchahaha/article/details/78026747一共有这么多中可能,1.直接将区间分成两部分,各消各的。2.如果两头是同色的,可以消完中间的,合并后消去两头,代价和两头的数量有关。3.如果两头同色原创 2017-09-19 19:10:46 · 370 阅读 · 0 评论 -
hdu 6197 array array array
经典的dp正着来个最长上升子序列,反着来个最长上升子序列,结束#includeusing namespace std;typedef long long ll;#define pb push_backint INF=1e9+7;const int mod=1e9+7;int n,m;int x;int g[100005],g1[100005],a[100005];int ma原创 2017-09-10 20:54:57 · 264 阅读 · 0 评论 -
Codeforces Round #436 (Div. 2) Fire
01背包的变形问题。#include #define pb push_back#define mp make_pairusing namespace std;struct node{ int t,d,p,i;}a[105];bool cmp(node a,node b){ return a.d<b.d;}int b[105];int dp[2005],p原创 2017-09-26 17:03:12 · 205 阅读 · 0 评论 -
51nod 1101 换零钱 (完全背包)
完全背包#includeusing namespace std;typedef long long ll;#define pb push_backconst int mod=1e9+7;int n,m;int a[13]={1,2,5,10,20,50,100,200,500,1000,2000,5000,10000};int dp[100009]={0};int main()原创 2017-08-31 21:13:30 · 382 阅读 · 0 评论 -
51nod 1134 最长递增子序列
二分加dp#includeusing namespace std;typedef long long ll;#define pb push_backint INF=1e9+7;const int mod=1e9+7;int n,m;int x;int g[50005];int main(){scanf("%d",&n);int ans=1;for(int i=1;i<=原创 2017-08-31 21:02:04 · 197 阅读 · 0 评论 -
hdu 6149 Valley Numer II (状态压缩dp)
枚举每个低点,最多和多少个高点,取最大值#includeusing namespace std;typedef long long ll;int h[50],a[50],map1[50][50];int dp[2][(1<<15)+10];int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt"原创 2017-08-30 14:47:19 · 348 阅读 · 0 评论 -
51nod 1021 石子归并(区间dp 详细解释)
区间dp模板题,好长时间没做过区间dp了,当初学的一点知识也忘得没有了,区间dp从小的区间,慢慢成大的区间,以2为区间,然后以3为区间……以3为区间就可以用到以2为区间,两堆石子合并,就是把这两堆石子的数量加一次,把i——j的石子合并,就是把i——j区间内的石子加一次,他们必须是连着的才能合并,如果区间为3,肯定是区间为2的和区间为1 的合并了一次,所以,区间为3的取他们的最小值就行了举个例子原创 2017-09-07 18:18:36 · 371 阅读 · 0 评论 -
51nod 1294 修改数组(dp,逆向思维,最大上升子序列)
------------------------------------看别人的代码写得题解---------------------------------------这个题和那个最大上升子序列很像,就是不是严格递增的最大上升自序列。首先应该去想如果a[i]-i小于0,必须要改,因为这个是按照严格的递增来排列的。剩下的就要找不是严格递增的最大上升自序列。用n-最大上升自序列,就是答案。如原创 2017-10-07 20:17:54 · 299 阅读 · 0 评论 -
51nod 1006 最长公共子序列Lcs
#includeusing namespace std;//以下为倍增算法求后缀数组int dp[1100][1100];char s[1100],s1[1100],s2[1100];int main(){ cin>>s; cin>>s1; int len1=strlen(s); int len2=strlen(s1); memset(dp,0,sizeof(dp)); f原创 2017-10-02 16:50:19 · 226 阅读 · 0 评论 -
51nod 1007 正整数分组(背包)
将一堆正整数分为2组,要求2组的和相差最小。例如:1 2 3 4 5,将1 2 4分为1组,3 5分为1组,两组和相差1,是所有方案中相差最少的。Input第1行:一个数N,N为正整数的数量。第2 - N+1行,N个正整数。(N Output输出这个最小差Input示例512345Output示例1原创 2017-10-02 17:20:07 · 244 阅读 · 0 评论 -
2014年山东省第五届ACM大学生程序设计竞赛Colorful Cupcakes
这个题可以说是记忆化搜索,和数位dp也有点相似。刚好做了一道数位dp,然后水了水这个。#include <bits/stdc++.h>using namespace std;char s[55];int dp[4][55][55][55][4];int mod=1e9+7; int a[5];int dfs(int now,int a,int b,int c,int fir...原创 2018-04-21 16:15:22 · 236 阅读 · 0 评论 -
第四届山东省赛 A-Number and B-Number [数位dp+二分答案]
A数组就是民间游戏”敲七”的序列 B数组就是{x∣∣xi∈{A}且i∉{A}}{x|xi∈{A}且i∉{A}} 然后输出B数组中第n个元素即:Bn数位dp建立dp数组一般都是3位,一位表示当前数,一位表示前面的,一位表示状态。前面就是%7 一共有7位,当前一共18位,状态有两个,一个是前面有7一个是没7。然后记忆化搜索,就是数位dp#include <bits/stdc++.h>us...原创 2018-04-20 14:32:19 · 180 阅读 · 0 评论 -
Codeforces Round #467 (Div. 2)D. Sleepy Game(记忆化搜索+状态压缩)
这个题目一看就是记忆化搜,只有深搜肯定超时,如果不状态压缩成奇偶的话,数组开不下,记忆化搜索就是一个套路,不再赘述,我开始只有深搜,超时了发现要记忆化。#include #define ff first#define ss second#define mp make_pairusing namespace std;typedef long long ll;vector G[10原创 2018-03-06 17:19:49 · 176 阅读 · 0 评论 -
Educational Codeforces Round 39 (Rated for Div. 2)D. Timetable(dp)
先对每一行进行处理,每一行中g[i][j]代表第i行除去j节课最少上的课数。知道了g[i][j],进行记忆化搜索,dp[i][j]代表第i行剩下k节课可以逃,最少上的课数。两个地方需要dp,水平不够啊啊啊啊啊。O(∩_∩)O哈哈~#include #define pb push_back#define fore(i,a,b) for(int i=a,ThxDem=b;i<ThxDe原创 2018-03-08 11:45:57 · 203 阅读 · 0 评论 -
Codeforces Round #460 (Div. 2)D. Substring
先判断是不是环然后记忆化搜索。杜教代码#includeusing namespace std;const int MX=300005;int f[MX][27];vectorG[MX];int n,m;char s[MX];char vis[MX];bool dfs(int k){ if(vis[k]==2)return false; if(vis[k]==1)retu原创 2018-02-02 21:58:15 · 527 阅读 · 0 评论 -
51nod 1833 环 (dp)
虽然标题是图论,我感觉和图论有关系,但是和dp关系更密切。我们发现这个不相交环其实就是把原图造成二分图的一个完全匹配。比如如果有一个i->j的边我们就在i->j'的二分图中建一个边。我们可以容易知道二分图的完全匹配就是不相交环覆盖的方案数。那么就可以用集合dp在O(n2^n)中找出所有完全匹配就可以了。就是枚举一下这个集合然后找一个固定元素出来求一下贡献就可原创 2017-11-03 14:47:33 · 834 阅读 · 2 评论 -
hihoCode #1338 : A Game (区间dp)
#1338 : A GameTime Limit:10000msCase Time Limit:1000msMemory Limit:256MBDescriptionLittle Hi and Little Ho are playing a game. There is an integer array in front of them.原创 2017-10-25 20:33:41 · 270 阅读 · 0 评论 -
Codeforces Round #442 (Div. 2) B. Nikita and string (记忆化搜索)
cf晚间档一反常态,B和C交换了难度,真是有趣。记忆化搜索,3种状态,暴力的搜一下,没想到这么做。还是道行不够。-----------------因为热爱,所以执着-----------------------#includeusing namespace std;#define pb push_back#define mp make_pairchar s[50原创 2017-10-24 18:47:58 · 267 阅读 · 0 评论 -
51nod 1424 零树(树dp)
dp【u】【0】代表根节点需要减的数,dp【u】【1】代表根节点需要加的数。#include using namespace std;const int maxn=1e5+5;vectora[maxn];long long dp[maxn][2];int v[maxn];void dfs(int u,int fa){ for(int i=0;i<a[u].size();i原创 2017-10-14 11:39:44 · 326 阅读 · 0 评论 -
51nod 1053 最大M子段和 V2 (链表 对经典dp进行优化)
把所有连续正数或者负数整合起来。比如 1 2 3 -1 -2 6 整合后是6 -3 6.这样用set存储他们的绝对值。每次让绝对值最小的和两边的进行整合。每次整合肯定会少一个正数。比如当前绝对值最小的是负数,把周围两个正数和这个负数进行合并。形成一个正数。把这三个去掉,入队新的这个正数。如果最小的为正数,正好把正数和周围的负数合并。少一个正数。最后剩下m个最大的正数序列就行了。每次少那个用所有正数原创 2017-10-05 10:48:19 · 454 阅读 · 0 评论 -
51nod 1052 最大M子段和 (区间dp)
看到大佬题解,感觉很全面动态规划,借助矩阵可以直观的看到计算过程。定义二维数组dp, dp[ i ][ j ],表示前 j 项所构成 i 子段的最大和,且必须包含着第j项,即以第j项结尾然后是一个递推过程。求dp[ i ][ j ],有两种情况1、dp[ i ][ j ] = dp[ i ] [ j-1 ] + a[ j ] ,即把第j项融合原创 2017-10-04 21:02:54 · 399 阅读 · 0 评论 -
51nod 1056 最长等差数列 V2
这个和1055那个题差不多,稍微改改就过了,首先是剪枝的改写,这个剪枝是必过的,唐老师在讨论里进行了证明。首先要明确等差数列的定义。一个等差数列可以用首项、公差和项数的三元组 (first,delta,length) 表示,当然这个 first 也可以换成末项 last ,取决于你的算法。我们要考虑的等差数列要尽量用少的信息表示所有的可能,也就是说提取出来的等差数列之间不能原创 2017-10-03 16:51:34 · 431 阅读 · 0 评论 -
51nod 1055 最长等差数列
n^2的算法可以做,先给数组a进行排序,遍历a【i】,让j=i-1,k=i+1.if(a[j]+a[k]>a[i])j--if(a[j]+a[k]41 2 3 4这组测试数据看着代码想想就可以了。#include #include#define ll long longusing namespace std;int a[10010];short i原创 2017-10-03 15:21:59 · 207 阅读 · 0 评论 -
51nod 1183 编辑距离
开始不知道怎么想的想偏了。。。很简单的三种情况,第一个字符串+1,第二个字符串+1,两个相同的情况dp不能想太多,想出,这个数怎么由前面的状态转移而成就行了。想的多,要背锅。#include #include#define ll long longusing namespace std;char s[2][1500];int dp[1500][1100];int main(原创 2017-10-03 11:59:38 · 161 阅读 · 0 评论 -
51nod 1042 数字0-9的数量
给出一段区间a-b,统计这个区间内0-9出现的次数。比如 10-19,1出现11次(10,11,12,13,14,15,16,17,18,19,其中11包括2个1),其余数字各出现1次。Input两个数a,b(1 Output输出共10行,分别是0-9出现的次数Input示例10 19Output示例1111111原创 2017-10-03 10:22:59 · 335 阅读 · 0 评论 -
hdu 6156 Palindrome Function(数位dp&&其他)
我的数位dp加上输入输出外挂还是超时了,罪过罪过。不过对于我理解数位dp 还是有帮助的#includeusing namespace std;typedef long long ll;int bit[38],temp[38];ll dp[38][38][38]; int p; int Scan(){ // 输入外挂 int res = 0, flag =原创 2017-08-29 20:04:57 · 240 阅读 · 0 评论 -
hdu 6148 Valley Numer (数位dp)
在强调一下记忆化搜索时间复杂度是O(n)这里面的记忆化搜索时间复杂度是10*N一共t组测试数据 10*N*t#includeusing namespace std;typedef long long ll;const int mod=1e9+7;char s[105];int bit[105];ll dp[105][12][5]; int len;ll dfs原创 2017-08-29 18:38:44 · 299 阅读 · 0 评论 -
51nod 1406 与查询
开始我是想着用记忆化搜索,没想好怎么去重,倒着推,可以去掉重复,不过确实不好想。比如一个数1011,先去掉开始的1,现在1011和0011都是1了,去掉第二个1,1001和0001都是1了,去掉第三个1,1011,1001,0001,1000,0000都是1了没有重复#include#include#include#include#includeusing namespace std原创 2017-09-14 21:53:42 · 350 阅读 · 2 评论 -
poj 1947 Rebuilding Roads
dp[s][i]:记录s结点,要得到一棵i个节点的子树去掉的最少边数 考虑其儿子k 1)如果不去掉k子树,则 dp[s][i] = min(dp[s][j]+dp[k][i-j]) 0 2)如果去掉k子树,则 dp[s][i] = dp[s][i]+1 总的为 dp[s][i] = min (min(dp[s][j]+dp[k][i-j]) , dp[s][原创 2017-03-08 21:40:05 · 329 阅读 · 0 评论 -
poj 3176 Cow Bowling
入一个n层的三角形,第i层有i个数,求从第1层到第n层的所有路线中,权值之和最大的路线。规定:第i层的某个数只能连线走到第i+1层中与它位置相邻的两个数中的一个。 思路:用逆推的思想,从后往前推,dp[i][j]=max(dp[i+1][j]+a[i][j],dp[i+1][j+1]+a[i][j]);#include #include #inc原创 2017-01-31 10:40:02 · 306 阅读 · 0 评论 -
poj 1260 Pearls
#include #include #include #include #include using namespace std;/*定义sum【i】是i之前所有宝石的数量*/int main(){ int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n);原创 2017-01-26 16:53:38 · 197 阅读 · 0 评论