hdu 3535 AreYouBusy

来源:互联网 发布:后期剪辑软件 编辑:程序博客网 时间:2024/05/17 23:16

hdu   3535   AreYouBusy              题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3535

                              

题目大意:小A要在一段时间内做一些工作,给出工作大类的数量n、总时间t。共有0、1、2三大类工作,0是老板要求至少做其中一项的、1是小A自己想做,但最多从中选一项的、2是随便的(注意所有工作只能做一次),每一大类里又有m种工作,每种工作有两个参数c和g,分别代表花费的时间和得到的快乐值,求最大快乐值。

题目分析:算是个混合背包吧,考虑三种情况,如下。

    至少要做一项的0:需要用到此刻状态(不装、再装)、上一状态(只装)。处理这一大类工作时先把此状态数组赋为-inf,这是为了不会出现一种工作都不选的情况。然后此种状态下的状态转移方程就是dp[此状态][i]=max(dp[此状态][i],dp[上一状态][i-c]+g,dp[此状态][i-c]+g);

    最多做一项的1:把上一状态全数复制到当前状态后开始装这一大类物品,这次复制为的是保留上一状态,写操作只在当前状态上。这一类工作可以选择做或不做,状态转移方程dp[当前状态][i]=max(dp[当前状态][i],dp[上一状态][i-c]+g);

    随便的2:就是个普通0-1背包。

还有个值得一提的地方,此题初学滚动数组,用的2×一维的开关变量控制的滚动数组,是从hdu1024市面上的代码里学来的。

code:

#include<stdio.h>#include<string.h>int max(int a,int b){return a>b?a:b;}int main(){int m,n,t,s,i,j,c,g,cur=0,dp[2][110];while(scanf("%d%d",&n,&t)!=EOF){memset(dp,0,sizeof(dp));while(n--){scanf("%d%d",&m,&s);switch(s){case 0:for(i=0;i<=t;i++)dp[cur][i]=-99999;while(m--){scanf("%d%d",&c,&g);for(i=t;i>=c;i--){dp[cur][i]=max(max(dp[cur][i],dp[1-cur][i-c]+g),dp[cur][i-c]+g);}}break;case 1:for(i=0;i<=t;i++)dp[cur][i]=dp[1-cur][i];while(m--){scanf("%d%d",&c,&g);for(i=t;i>=c;i--){ dp[cur][i]=max(dp[cur][i],dp[1-cur][i-c]+g);}}break;case 2:cur=1-cur;//懒得再赋值了,一样while(m--){scanf("%d%d",&c,&g);for(i=t;i>=c;i--){dp[cur][i]=max(dp[cur][i],dp[cur][i-c]+g);}}}cur=1-cur;}for(i=0;i<=t;i++){n=max(n,dp[1-cur][i]);}printf("%d\n",n);}return 0;}

PS:参考了discuss里的代码,这次discuss里只有一篇代码……还有很多值得修改的地方,我删了不少微笑

开始看代码有很多不懂,感谢大神http://www.cnblogs.com/coredux/archive/2012/07/26/2610868.html





0 0
原创粉丝点击