随笔分类 - 动态规划
ACM重点
    
摘要:http://www.lightoj.com/volume_showproblem.php?problem=1031给你n个数,A、B两个人从两端取数,每一次可以取连续的一段数,而且每个人都按让自己最优的方案去取数(即取的数的和尽可能大)问最后A与B的差值最大是多少解法:枚举区间长度,从小区间DP到大区间对于一段区间,枚举分隔点,要么取左边,要么取右边下面是两种写法View Code #include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int inf 
        阅读全文
            
摘要:蛮有意思的一个题给你一个字符串,再给你k对字符要求删掉一些字符使得字符串中不存在相邻的字符是这k对中的某一对首先如果一个字符只出现在k对中的某一对中,那么可以贪心做因为不会出现如下情况了 : aaaabbbcccc2abac即不会出现删了之后前面的字符缩进来还会出现矛盾但是当可以出现这种情况怎么办DP就派上用场了dp[i][j]表示前i个字符处理完了之后最后一个字符为(j+'a')的最小需要删掉的字符那么到某个i位置的时候,首先不管它和前面留下来的最后一个字符有没有矛盾,都可以将它删除掉如果没有矛盾,我们还可以将状态转移为以当前字符结尾View Code #include<
        阅读全文
            
摘要:把所有的背包结合起来的一道终极背包题,做了的话背包一般就没问题了题意:给你n个种类的物品的描述,背包容量D每个种类有三个属性 K E PK表示这类物品最多可以选多少个,如果为0表示可以选无限多个E表示选择这类物品每个物品的价值P表示每个物品的花费如果单纯是这样,那这道题目就太水了,直接多重背包就ok了所以题目又加了点,而这一点想了我n久 啊题目还将一些种类的物品分了个组,每组种类中最多只能选一个种类的物品即加上了分组背包,按理说再往多重背包上套个分组背包不久好了,但是仔细想想发现每一组物品是由一些种类的物品组成的,只能在里面选一类,而每一类物品又有自己的性质,所以不好搞。做法是这样的:开个临时
        阅读全文
            
摘要:很好的树形DP,破环为树;这道题目很特殊,看到的时候根本无从下手,因为以前没接触过这种类型的树形DP,网上搜了一下发现自己简直弱爆了。。这是一类最简单的树形DP,考虑某个节点选或不选,然后把两种状态从叶子向根更新上去即可,但是这道题中给你的不是一棵树,是图,特殊的图每个点都只有一个父亲(或一个儿子),所以形成的环是简单环,所以可以考虑破环,从环上的一个点出发开始DP,这个点的两种状态(选或不选)分别枚举一下View Code #include<cstdio>#include<cstring>#include<algorithm>using namespace
        阅读全文
            
摘要:主要能解决的问题n个数中选取k个不相邻的数,使得这k个数的总和最小View Code #include<cstdio>#include<cstring>#include<algorithm>using namespace std;int dp[2010][1010];int a[2012];const int inf = INT_MAX;int main(){ int n,k; while(scanf("%d%d",&n,&k)!=EOF) { for(int i=1;i<=n;i++) scanf("%d
        阅读全文
            
摘要:有n个点排成一行,每两个点有一个权值。现在你可以从任何一个点出发,去遍历其他点,每经过两个相邻点之间的边,边的权值就会减1,求最多能走的步数用两个dp数组记录往左走和往右走的最大步数dp1[i][0]表示从i往左走最多能走的步数dp1[i][1]表示往左走并回到i最多能走的步数dp2同理然后遍历一遍就可得答案View Code #include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 100010;long long num[maxn];l
        阅读全文
            
摘要:zoj 3611同类型的题目poj 2688化简模型即可得这样的问题,一幅图给定起点 终点 ,求起点到终点最多经过几个点,如果两种方案经过的点数相同,选路径总长短的注意,这幅图最多只有12个点,所以立刻可以想到用状态压缩来做dp[i][j]表示以i为终点的路径 为j状态(经过了那些点)时的最短路径ps:在预处理最短路的时候不要将'$'算进去,就看成一个普通的可以走的格子就可以了因为可能会出现如下情况,'$'的费用会算了四次,所以还是先数一下有几个'$'然后再独立算吧View Code #include<cstdio>#include&
        阅读全文
            
摘要:哎,CF终于变色了A题:我写了个二分,囧。。。B题:模拟题,水C题:想了半天,水王(一学长)告诉我是DP,果断敲了dp[i][j]表示i字符走到j字符最大的权值View Code int dp[30][30];int max(int a,int b){ return a>b?a:b;}int main(){ int n,i,j,k; char s[15]; while(scanf("%d",&n)!=EOF) { memset(dp,0,sizeof(dp)); for(k=1;k<=n;k++) { ...
        阅读全文
            
摘要:A题:水题B题:水题C题:用栈来做D题:数学题,需要仔细地分类讨论E题:给你n个数围成一个环,若两个数之间没有比他们更大的数,则称两个数是一对合法的数问n个数中共有几对数合法类似于动态规划,一个相似的题目先破环,变成一条线,把最大的元素放到两个端点(增加了一个元素)用两个数组l[],r[] l[]记录某元素往左边第一个严格大于它的数的位置,r[]记录某元素的右边第一个严格大于它的数的位置。c[i]记录i位置的数与l[i]或r[i]之间等于num[i]的数的个数具体见http://codeforces.com/blog/entry/213代码写的有点搓View Code #include<
        阅读全文
            
摘要:http://202.120.106.94/onlinejudge/problemshow.php?pro_id=542背包练习题简单的概括下题意有一个函数 f(x)现有n个未知数x1 x2 x3....xnsigma(xi)= S求f(x1)+f(x2)+f(x3)+..+f(xn)的最大值n s 的最大值都是100这不就是泛化背包吗?每个物品的价值随着你分配给它的体积的变化而变化,最后求体积为S的背包能装进的物品的最大价值注意相同答案时 要输出前面的体积尽可能大的方案,我很懒,可以参考 这里View Code #include<cstdio>#include<cstrin
        阅读全文
            
摘要:ABC水题D:n个二元组,求最长的一个序列组seq,序列的每一个元素的两个值都分别大于前一个元素记忆化搜索或者筛选后DP都可以两种方法View Code #include<cstdio>#include<cstring>#include<set>#include<string>#include<iostream>#include<map>#include<vector>#include<algorithm>using namespace std;#define DEBUG printf("
        阅读全文
            
摘要:A题:模拟题,仔细点就好B题:DP给你一个数字矩阵,要求从左上角走到右下角的一条路径,这条路径上的数乘起来后末尾的0的个数最少末尾的0是由2、5产生的,于是联想一下是不是走2最少的一条路或者5最少的一条路就ok了呢?嗯,就是ok的.*_*假设从左上角走到右下角走过的数含因子2的最小的个数是x,5的最小的个数是y,则答案是min(x,y),即最优解x、y的个数中有一项是最少的证明:用反证法,假设最优解经过的数含a个2,b个5,a>x,b>y,易得答案肯定大于min(x,y),所以最优解的x、y肯定有一项是最小的View Code #include<cstdio>#incl
        阅读全文
            
摘要:要解决的核心问题是:求1~x(在base进制下)的区间内各数位上的数字之和恰好为m的数的个数对于每一个询问,先预处理一个DPdp[i][j]表示在base进制下 长度为i且 数位之和为j的数的个数然后在calc()中一位一位统计过去就好了View Code #include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef __int64 lld;lld dp[32][331];//dp[i][j]:长度为i,数位和为j时的数的个数void init(int lim,
        阅读全文
            
摘要:1-n的排列题目给出m对 a b,表示a位置放b问你满足其中至少一对关系的总排列数反过来求,先求出一对关系都不满足的排列数,在用总的排列数减去它具体做法是对于每个位置,枚举那些不能放的数放在这个位置,不断地去更新状态数组#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef __int64 lld;lld fac[20];lld dp[1<<19];int re[20][20];void init(){	fac[0]=1;	for(int i=
        阅读全文
            
摘要:View Code /*给你n个物品,每个物品有一定的体积,给你一个总体积一定的背包,问你用这个背包去装这些物品的时候,背包中的物品共有几种不同的组合一种组合是合法的:剩下的背包容量必须《剩下的物品的体积的最小值*/#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int dp[1010];int v[50];int max(int a,int b){ return a>b?a:b;}int main(){ int t,i,j,k,V,D,ca=1; scan
        阅读全文
            
摘要:参考了这里http://blog.sina.com.cn/s/blog_6a6aa7830100x890.html题意:有N条赛道,每一条初始时都是坏的,修复第i条赛道的费用是cost[i];赛道上会举办m个赛事,每个赛事会用到[L,R]之间的赛道,而且要保证赛事进行必须使得这一段的赛道完好,每项赛事还可以获得一定的钱数。问题要求安排哪些比赛可以使得收益最大。可以设dp[i]表示到i这个赛道为止能获得最大的利益有状态转移方程dp[i]=max(dp[i-1],dp[j]+benefit[j+1][i]-mend[j+1][i]);注: j+1->i之间有赛道数据范围200000 暴力的话
        阅读全文
            
摘要:http://www.codeforces.com/problemset/problem/182/E给你n中篱笆,每种篱笆都有一个长和一个宽,设为a[i],b[i],再给你一个长度L问用这些篱笆的长可以组成多少长度为 L 的漂亮的篱笆漂亮的定义: 1、相邻的两个篱笆要属于不同的种类 2、 后一个篱笆的长必须等于前一个篱笆的宽注意:一个篱笆的两个边长都可以作为长因为所选的每个篱笆都有两种状态,一种是用a[i]作为长,一种是用b[i]作为长所以可以设dp[i][j][0]表示组成i长度的篱笆,最后一个为第j个篱笆,且第j个篱笆用a[i]作为长的方案数同样dp[i][j][1]表示第j...
        阅读全文
            
摘要:已经做过一个类似的题目了,只是这道题目求的是最长的长度,那个题目求的是总的这样的序列的个数,都是用线段树或者树状数组来优化求和操作,使之降为log(n)View Code #include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int maxn = 100010;int sum[maxn<<2];int num[maxn];int
        阅读全文
            
摘要:hdu 1561 The more, The Better树形DP入门 利用分组背包的思想#include<cstdio>#include<vector>#include<cstring>using namespace std;int dp[250][250];vector<int> edge[250];int n,m;int val[250];int max(int a,int b){	return a>b?a:b;}/*/////////////////////////////////////////////分组背包:for 所有的组i
        阅读全文
            
摘要:题目链接http://www.codeforces.com/contest/11/problem/D题目的点数不超过20,所以利用状态压缩DP可解dp[i][j]表示i状态时以j结尾的简单路径的数量,i的二进制表示中为1的表示这个点在路径中i的二进制中最低位1表示的点是起始点View Code #include<cstdio>#include<cstring>typedef __int64 lld;const int maxn = 19;lld dp[1<<maxn][maxn];//int mp[maxn][maxn];int main(){ int n,
        阅读全文
            
 
                    
                
 
 浙公网安备 33010602011771号
浙公网安备 33010602011771号