随笔分类 - DP
摘要:这个题是一个期望DP题:假设从a要走到d,a与b,c连通,b,c与d连通,那么从a到d的期望就是就是a到b的概率乘以b到d的期望,加上a到c的概率乘以c到d的期望,再加上花费;我们注意到这个题的bug是无穷的,那么从每个子程序找到bug的概率是1/s,而属于那种类型的是1/n;这里我们设dp[i][j]为找到从j种子程序中找到了i中类型;那麽dp[n][s]=0;代表已经到了目标;那么dp[i][j]与哪几种可能相连,有4种可能,dp[i][j],代表发现i中bug从j个子程序中找到的;dp[i+1][j],找到新的种类bug,从j个子程序;dp[i][j+1],i种类bug,从j+1个子程序
阅读全文
摘要:该题要用分组背包做,这里就是要怎样处理0必须选,1最多选一个,2任意选的问题;这里我们就开个二维数组;f[i][j],i表示第组,j表示时间;当该组为0时,我们在该组的选择可以来自上一组的结果,也可以来自该组的结果;如果为1那么结果只能依赖上一组的结果,如果依赖本组那么就会造成该组会多选;为2是那就是一个01背包;View Code #include<cstdio>#include<iostream>#include<cstring>using namespace std;class node{public: int cost,happy;};class N
阅读全文
摘要:该题是一道分组背包题;题意就是ACboy发最多M的时间能够得到最多效益;输入有N没课程,没门课程发费j天得到的效益是map[i][j];View Code #include<iostream>#include<cstdio>#include<cstring>using namespace std;int map[124][124];inline int Max( int a , int b ){ return a > b ? a : b; }int DP( int N , int M ){ int f[124][124] ={ 0 }; for( in
阅读全文
摘要:该题就用反方向思考,就是p = 1.0 -p 就可以了,不安全系数变成安全系数,再把安全系数相乘就可以了;View Code #include<iostream>#include<cstdio>#include<cstring>using namespace std;int ZeroOnepack( double pro[] ,int value[],double p ,int N, int sum ){ double f[10024] ={ 1.0 }; for( int i = 0 ; i < N; i++ ) { for( int j = sum
阅读全文
摘要:这是我A的第一个分组背包,这就没有用优化,这是暴力的,这里优化可以先对分组进行排序,那样就会节约好多的时间;分组背包是:有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。这里我们就可以设计成一个二维数组,f[kind][money],(kind表示当前已经拥有的品牌种类数目,money 表示当前已经花费了的前的数目)。当前状态的来源有二:A、当前品牌数目的前提之下取最大的值;B、在比当前品牌数目少的基础之上放一个另外品牌的商品的最大值;
阅读全文
摘要:一道简单的动态规划题,与http://acm.hdu.edu.cn/showproblem.php?pid=2084数塔思想是一样的,都是从后面往前面推;View Code #include<iostream>#include<cstdio>#include<cstring>using namespace std;int map[100024][12];int sum[100024][12];inline int Max( int a , int b ){ return a > b ?a : b;}int main( ){ int n,place, T
阅读全文
摘要:这个题我们可以直接顺序往下面暴力,每次选取最大的;View Code #include<iostream>#include<cstring>#include<cstdio>using namespace std;int main( ){ int Case ,n ,m; int map[24][1024],sum[24][1024]; while( scanf( "%d", &Case )==1 ) { while( Case -- ) { memset( map , 0 ,sizeof( map ) );// memse...
阅读全文
摘要:View Code #include<iostream>#include<cstdio>#include<cstring>#include<vector>using namespace std;vector<int>list[124];int value[124],num[124];int dp[124][124];int hash[124];void DFS( int f ,int M ){ int len = list[f].size(); int t=0; t = (num[f]+19)/20; for( int i = t ;
阅读全文
摘要:链接:http://acm.hdu.edu.cn/showproblem.php?pid=1561这题是一道树形DP(依赖背包);这是我学树形DP的做的第一题,这种背包问题的物品间存在某种“依赖”的关系。也就是说,i依赖于j,表示若选物品i,则必须选物品j。为了简化起见,我们先设没有某个物品既依赖于别的物品,又被别的物品所依赖;另外,没有某件物品同时依赖多件物品。对于这种背包我们可以建立成一棵树,父节点就是子节点所要依赖的;根据题意知道我们选择如果要打该节点,那么必要打掉该父节点;如果打父节点,总共还剩N次可以打的机会,那么我们可以对于子节点是打还是不打,打得时候可以分给该节点几次,我们就从这
阅读全文
摘要:这是一道多重背包的题目;题意:有N那种物件,每种物件有个重量与个数;求A要般的重量不比B的轻,但要使他们的重量只差最小;#include<iostream>#include<cstdio>#include<cstring>using namespace std;void Completepack( int value, int sum ,int f[] ){ for( int i = value ; i<= sum ; i++ ) if( f[i] < f[i-value] + value ) f[i] = f[i-value] + value;
阅读全文
摘要:该题是一道简单的DP题,我采用两头分别求最大的和,先顺序求每个数段的最大和,然后反过来求每个数段的最大的和;分析:先求顺序从左到右到该数的最大和;反序就是SUM[i-1]=SUM[i]+num[i-1#include<stdio.h>#include<stdlib.h>#include<string.h>int main(){ int n,T,num[50024],sum[50024],a,SUM[50024]; scanf( "%d",&T ); while( T-- ) { memset( sum,0,sizeof( sum
阅读全文
摘要:该题要注意的就是每张单子A种类的总和不能大与600,同样B,C类也一样,刚开始我就错了这里,还有注意如果不是A,B,C类的不可以报销;该题就是要把浮点型变成整数这样才能用01背包,这里就只要乘以100就可以了。#include<stdio.h>#include<stdlib.h>#include<string.h>int f[5000024]={0};int DP( int num[],int count, int sum ){ memset( f,0,sizeof( f ) ); for(int i=0;i<count; i++) { for( in
阅读全文
摘要:首先相信你已经看过《背包九讲》。对于每一次决策后,我们都能得到一组值:F[ i, j] I 表示进行了i次决策,j表示占用了j 的体积。最终获得了F[i,j]的收益。这么考虑的话,很显然,就能得到最优子结构的性质:如果最终能得到Fmax[ n, v ] ,那对于每一组i,j 必定 F[i,j]=Fmax[i,j]。因此,在遍历树的时候,如果两种决策有相同的i,j 那我们可以取出两者中的最大值,另外一种就被无情的抛弃了-_- 。这样,对于每一组的i,j 我们可以方便的按如下方程求出:F[i,j]=max( F[i-1,j] , f[i-1][j-volume[i]] + value[i] ) 按
阅读全文
摘要:该题只是在完全背包基础之上加了一个条件,就是只能杀s个怪,那么我们就对每次记录每次在该忍耐点所杀的怪,如果所杀的怪大于所给的数目,那么我们就不更换经验值。怎样计算所剩的忍耐点,我们知道每一个忍耐点都是所杀怪所得到的经验值最大,那么我们只要对f进行遍历一遍,如果经验值大于等于所给的经验值,代表在该忍耐点已经可以获得了升级。#include<stdio.h>#include<stdlib.h>int DP( int add[],int reduce[], int n, int m, int k,int s ){ int f[124]={0},hash[124]={0},;
阅读全文
摘要:该题WA了几次,一直找不出错误,后来经过livs的指导,我们先拿出5元,这5元一定是买价钱最贵的菜,这样才能保证剩余的钱最少,那么我们还要做一件事就是选取最贵的菜,这两件事处理好了,就是一件简单的01背包。#include<stdio.h>#include<stdlib.h>int ZeroOnePack( int price[],int money,int n ,int pos,int max){ int f[1024]={0}; for( int i=1; i<=n; i++ ) { if( i!=pos ) for( int j=money-5 ; j>
阅读全文
摘要:该题是母函数的变种,也是一种多重背包问题,由于写了几篇这样的,所以就不重累述了,如果不懂可以看一下背包九讲;#include<stdio.h>#include<stdlib.h>int CompletePack( int f[],int val,int money ,int sum)//完全背包{ for( int i=val; i<=money;i++ ) { if( i>=val&&f[ i-val ]+val>f[i] ) { f[i]=f[i-val]+val; if( f[ i ]==i )//如果相等,则代表有这种情况 {
阅读全文
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=2191#include<stdio.h>#include<stdlib.h>void CompletePack( int price,int f[],int money,int weight )//完全背包{ for( int i=price; i<=money; i++ ) { if( f[ i-price ]+weight>f[i] ) { f[i]=f[i-price] + weight; } } }void ZeroOnePack( int price,int nu
阅读全文
摘要:今天学了一下多重背包,这是我A的第一个题,刚开始用用比较暴力的,没优化的多重背包就TLE了。代码如下:#include<stdio.h>#include<stdlib.h>int DP( int val[], int N ){ int f[100024]={0}; for( int i=1;i<=6; i++ )//取不同的元素 { for( int j=1; j<=val[i]; j++ )//取元素的个数 { for( int k=N; k>=0; k-- ) { int t=j*i; if( t<=k&&f[ k-t ]+t
阅读全文
摘要:该题利用了我们的逆向思维,同时要注意该题他的质量是一定的,也就是说背包一定要是满的,刚开始对于这类背包我们令初始值是负无穷,而这题则相反,令初始值是正无穷,每次区最小的数,同时要注意f[j-weight[i]]!=inf应为一相等就与背包一定要满的条件相矛盾;#include<stdio.h>#include<stdlib.h>const int inf=0x7fffffff;int DP( int weight[],int val[],int N,int vol ){ int f[50024]={0}; for( int i=1; i<=vol; i++ ) f
阅读全文
摘要:这是一道赤裸裸的简单的完全背包,在HDU 2602中我说过在01背包优化的算法中提醒要注意v V--0,而不是0--V ,其实反过来就是完全背包;这个算法使用一维数组,先看伪代码:for i=1..N forv=0..Vf[v]=max{f[v],f[v-cost]+weight}你会发现,这个伪代码与P01的伪代码只有v的循环次序不同而已。这里还是要啰嗦一下,#include<stdio.h>#include<stdlib.h>int a[3]={ 150,200,350 };int DP( int money ){ int f[10024]={ 0 }; for(
阅读全文

浙公网安备 33010602011771号