HDU 3535 AreYouBusy(组合背包)
来源:互联网 发布:云计算的好处有哪些() 编辑:程序博客网 时间:2024/06/10 00:27
题目链接:点击打开链接
刚开始还以为是混合背包……
刚从一个难以处理背包上限的题走出来了,又进入一个考初始化的题,这是道好题啊好题!
题目大意:给你n组工作集合去选择和T分钟去完成它们,接下来有n组数据,每一组数据首先各给你一组m和s,m表示该组的工作数目,s表示你的选择方式(1.s=0表示至少选一个;2.s=1表示最多选一个;3.s=2表示自由选择),接着是m个工作,对应告诉你每个工作的工作时间ci和幸福指数gi,求:在T时间内能获得的最大幸福指数。
解题思路:如果最后存在一个最优解,即使互换工作集合的处理顺序,最后还是可以得到最优解,所以每个工作集合的工作选择是各自独立的,我们可以分开处理不同集合。
这道题用二维数组dp[ i ] [ j ] 来解,i 表示第几组,j 表示给定时间。每得到一组工作集合的数据就进行一次dp,所以dp[ i ][ j ]就是第i组的工作幸福指数。 三种情况分析如下:
1.第一类(s=0):至少在该组选择一个,即:不能不选,必须要选。在一开始就要将i=0时dp初始化为0,其他的初始化为-INF,这样就可以避免不选的情况了,并且,因为在题目中给出的ci,gi的取值可以为0,即可以有耗时和幸福度为0的选择,所以在初始化的时候要注意!。本类的dp数据可以由上一组的dp【i-1】来更新,也可以由当前组的前一个来更新后一个。因为该类中的dp一开始全部初始化为负无穷大,所以在选取时,要分是不是第一次拿,因此得到如下状态转换方程:
dp[ i ][ j ] = max( dp[ i-1 ][ j ] , dp[ i-1 ][ j - c ] + g , dp[ i ][ j ] + g );
2.第二类(s=1):最多选一项,即:选一个或者不选。该组的数据要从上一组更新而来,所以一开始要把上一组的数据复制过来。初始化工作:dp[ i ][ j ]=dp[ i-1 ][ j ];
状态转换方程:dp[ i ][ j ] = max ( dp[ i ][ j ],dp[ i ][ j - c ] + g );
3.第三类(s=2):自由选择,想选就选,不选就不选,普通的01背包问题。与第一类的区别就在于可以不选,所以初始化的时候不用讲究,直接将上一组的数据复制过来就行了。初始化前面一类中已给出,状态转移方程:dp[ i ][ j ]=max( dp[ i ][ j ],dp[ i ][ j - c] + g) ;
代码如下:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100+5;#define INF 1e8int n;int t;int dp[maxn][maxn];int cost[maxn];int val[maxn];int main(){ while(~scanf("%d%d",&n,&t)) { memset(dp,0,sizeof(dp)); for(int i=1; i<=n; i++) //这里一定要在i=1开始循环,我就是从0开始,然后就一直错,半天找不出错啊难啊,哭死 { int m,s; scanf("%d%d",&m,&s); for(int k=1; k<=m; k++) scanf("%d%d",&cost[k],&val[k]); if(s==0)//至少选1个的01背包问题 { for(int j=0; j<=t; j++) dp[i][j]=-INF; for(int k=1; k<=m; k++) for(int j=t; j>=cost[k]; j--) //逆序 { dp[i][j] = max( dp[i][j], dp[i][j-cost[k]]+val[k] ); //第一次拿的数据要从上一组更新而来 dp[i][j] = max( dp[i][j], dp[i-1][j-cost[k]]+val[k] ); } } else if(s==1)//至多选1个的背包问题 { for(int j=0; j<=t; j++) dp[i][j]=dp[i-1][j]; for(int k=1; k<=m; k++) for(int j=t; j>=cost[k]; j--) //j可以正序或逆序枚举 dp[i][j] = max( dp[i][j], dp[i-1][j-cost[k]]+val[k] ); } else if(s==2)//自由选择选的01背包问题 { for(int j=0; j<=t; j++) dp[i][j]=dp[i-1][j]; for(int k=1; k<=m; k++) for(int j=t; j>=cost[k]; j--) //逆序枚举 dp[i][j] = max( dp[i][j], dp[i][j-cost[k]]+val[k] ); } } int ans = max(dp[n][t],-1); printf("%d\n",ans); } return 0;}
~ step by step
- HDU 3535 AreYouBusy(组合背包)
- hdu 3535 AreYouBusy(组合背包)
- HDU 3535(AreYouBusy)组合背包的混合背包
- HDU 3535 AreYouBusy 综合背包
- hdu 3535 AreYouBusy(背包)
- HDU 3535 AreYouBusy(混合背包)
- hdu 3535 AreYouBusy 混合背包
- hdu 3535 AreYouBusy 混合背包
- [HDU 3535] AreYouBusy 混合背包
- HDU - 3535 AreYouBusy(混合背包)
- hdu 3535 AreYouBusy 混合背包
- hdu 3535 AreYouBusy(各种分组背包)
- hdu 3535 AreYouBusy(混合分组背包)
- HDU 3535 AreYouBusy 经典混合背包
- hdu 3535 AreYouBusy[各种分组背包]
- HDU 3535 AreYouBusy 经典混合背包
- HDU 3535 AreYouBusy(混合背包)
- hdu 3535 AreYouBusy(经典分组背包)
- js中的数组
- 在oracle如何产生一列总和不变的随机数
- 奔溃检测方法
- 【脚下生根】之深度探索安卓OpenGL投影矩阵
- 正则表达式匹配正负小数以及整数
- HDU 3535 AreYouBusy(组合背包)
- 【脚下有根】之Skia库的matrix代码解读
- ARKit从入门到精通(6)-ARSession介绍
- 2017 Multi-University Training Contest 2 solutions 1001 Is Derek lying?
- 坐标架内转换到坐标架外的公式
- d3.js-选择、插入、删除元素
- C++进阶 -类中成员和成员函数的动态调用
- 7.31-8.6学习总结
- WordPress版微信小程序2.1.5版发布