HDU3535 AreYouBusy 混合背包
题目大意
给出几组物品的体积和价值,每组分为三种:0.组内物品至少选一个;1.组内物品最多选一个;2.组内物品任意选。给出背包容量,求所能得到的最大价值。
注意
- 仔细审题,把样例好好看完了再答题,否则非常浪费时间!
混合背包
定义DP(i,j)为轮到第1~i组背包内物品总体积严格为j时所能得到的最大价值,实现用滚动数组。(以下i或i-1后都&1)
种类2
把当前的DP(i,..)当作一个关于背包的一维覆盖数组(因为是关于整个背包的数组,所以要把DP(i-1,...)的值拷贝到一维覆盖数组中),对该组内所有物品在背包内进行01背包即可。递归式DP(k,j)=max{DP(k-1, j), DP(k-1, j-v[k])+w[k]}.
注意
- 因为DP在一个一维覆盖数组内进行,所以DP内的第一个参数永远是i。
种类1
在整个背包内进行一遍分组背包即可。递归式为DP(i,j)=max{DP(i-1, j), max{DP(i-1,j-v[i][k])+W[i][k] | k属于组i}}
注意
- DP中第一个参数的值总是i-1。
种类0
01背包中,如果DP(i-1, j)>DP(k=1, j-v[k])+w[k]且每个DP(k-1, j)>DP(k,j-v[k]+w[k])可能会导致该组的物品一个都不选,但是DP值小一点不要求最大可能也能满足题意。此时就要对每一个k提供几个总价值小一点的选择,包括k-1所代表的稍小值(规定k-1的较小值是1~k-1中较小值中最大的),或不要k-1等物品,直接在i-1组放入k所代表的较小值(两个较小值不一定谁大呢)。
对于每个物品k,三种操作:选:1.在k之前的物品的基础上放入k,2.在i-1组内的基础上放入k。3.不选(k以前物品选出了一个则有解,否则再也没办法有解了)
即使不存在一开始所说的情况,1,3也是标准的01背包。以上取最大值即可。
注意
- 一开始数组是清空的。
注意
- 只在一开始对DP[0][0]设为0,其余设为-INF。对于每个组不要设置DP[i][0]。
- 循环体积要一直循环到0,因为有体积为0的物体。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cassert>
using namespace std; const int MAX_GROUP = 110, MAX_V = 110, MAX_EACH_OBJ = 100, MAX_TYPE = 3;
int V[MAX_GROUP][MAX_EACH_OBJ], W[MAX_GROUP][MAX_EACH_OBJ], Type[MAX_GROUP], ObjCnt[MAX_GROUP];
int totGroup, totV; int Proceed()
{
static int DP[2][MAX_V];
memset(DP, 0xcf, sizeof(DP));
DP[0][0] = 0;
for (int i = 1; i <= totGroup; i++)
{
memset(DP[i & 1], 0xcf, sizeof(DP[i & 1]));
switch (Type[i])
{
case 0://至少选一个
for (int k = 1; k <= ObjCnt[i]; k++)
{
for (int j = totV; j >= V[i][k]; j--)
{
DP[i & 1][j] = max(DP[i & 1][j], DP[i & 1][j - V[i][k]] + W[i][k]);
DP[i & 1][j] = max(DP[i & 1][j], DP[(i - 1) & 1][j - V[i][k]] + W[i][k]);
}
}
break;
case 1://最多选一个
memcpy(DP[i & 1], DP[i - 1 & 1], sizeof(DP[i - 1 & 1]));
for (int j = totV; j >= 0; j--)
for (int k = 1; k <= ObjCnt[i]; k++)
if (j >= V[i][k])
DP[i & 1][j] = max(DP[i & 1][j], DP[i - 1 & 1][j - V[i][k]]+W[i][k]);
break;
case 2://随便
memcpy(DP[i & 1], DP[i - 1 & 1], sizeof(DP[i - 1 & 1]));
for (int k = 1; k <= ObjCnt[i]; k++)
for (int j = totV; j >= V[i][k]; j--)
DP[i & 1][j] = max(DP[i & 1][j], DP[i & 1][j - V[i][k]] + W[i][k]);
break;
default:
assert(0);
}
}
int ans = -1;
for (int j = 0; j <= totV; j++)
ans = max(ans, DP[totGroup&1][j]);
return ans;
} int main()
{
#ifdef _DEBUG
freopen("c:\\noi\\source\\input.txt", "r", stdin);
freopen("c:\\noi\\test\\output.txt", "w", stdout);
#endif
while (~scanf("%d%d", &totGroup, &totV))
{
for (int group = 1; group <= totGroup; group++)
{
scanf("%d%d", group + ObjCnt, group + Type);
for (int obj = 1; obj <= ObjCnt[group]; obj++)
scanf("%d%d", obj + V[group], obj + W[group]);
}
printf("%d\n", Proceed());
}
}
HDU3535 AreYouBusy 混合背包的更多相关文章
- HDU 3535 AreYouBusy(混合背包)
HDU3535 AreYouBusy(混合背包) http://acm.hdu.edu.cn/showproblem.php?pid=3535 题意: 给你n个工作集合,给你T的时间去做它们.给你m和 ...
- UESTC 424 AreYouBusy --混合背包
混合三种背包问题. 定义:dp[i][k]表示体积为k的时候,在前i堆里拿到的最大价值. 第一类,至少选一项,dp初值全赋为负无穷,这样才能保证不会出现都不选的情况.dp[i][k] = max(dp ...
- HDU 3535 AreYouBusy (混合背包)
题意:给你n组物品和自己有的价值s,每组有l个物品和有一种类型: 0:此组中最少选择一个 1:此组中最多选择一个 2:此组随便选 每种物品有两个值:是需要价值ci,可获得乐趣gi 问在满足条件的情况下 ...
- HDU 3535 分组混合背包
http://acm.hdu.edu.cn/showproblem.php?pid=3535 题意:有n组工作,T时间,每个工作组中有m个工作,改组分类是s,s是0是组内至少要做一件,是1时最多做一件 ...
- Codevs 3269 混合背包(二进制优化)
3269 混合背包 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description 背包体积为V ,给出N个物品,每个物品占用体积为V ...
- HDU3535——AreYouBusy
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3535 题目意思:给出两个数n,T,分别表示有n个任务集合,T的总时间,对于每个任务集合有两个属性m和t ...
- codevs 3269 混合背包(复习混合背包)
传送门 [题目大意]给出物品的数量.-1为无限个. [思路]混合背包.... [code] #include<iostream> #include<cstdio> #inclu ...
- [codevs3269]混合背包
题目大意:一道混合背包模板. 解题思路:分三种情况讨论,01和完全没什么问题,多重背包需要把物品分成$\log W[i]$件,然后01即可,分成W[i]件01会TLE. 读优大法好! C++ Code ...
- CODE[VS] 3269 混合背包
3269 混合背包 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 背包体积为V ,给出N ...
随机推荐
- PHP操作多进程
在以往的开发项目中,要操作进程就会使用PHP自带的pcntl拓展.但是pcntl存在着许多的不足: pcntl没有提供进程间通信的功能 pcntl不支持重定向标准输入和输出 pcntl只提供了fork ...
- js基础---数组方法
数组数据的排序及去重 sort无形参的排序方式 arr1=[2,12,3,15]; var a=arr1.sort();console.log(arr1);console.log(a);//排序会改变 ...
- 大白话理解cookie
HTTP协议是一个无状态的协议,服务器无法区分出两次请求是否发送自同一服务器. 需要通过会话控制来解决这个问题,会话控制主要有两种方式Cookie 和 Session. Cookie就是一个头,Coo ...
- python--7、面向对象
什么是面向对象 对象,即抽象的一类事物中的某个具体的个体.这个世界中存在的一切皆为对象,不存在的也能创建出来. 较之面向过程的区别: 编程的复杂度远高于面向过程,不了解面向对象而立即上手基于它设计程序 ...
- js-常见简单的js判断方法(暂不参考正则)
1: 2: 3: 4: 5: 6: 7:
- SQL优化--使用 EXISTS 代替 IN 和 inner join来选择正确的执行计划
在使用Exists时,如果能正确使用,有时会提高查询速度: 1,使用Exists代替inner join 2,使用Exists代替 in 1,使用Exists代替inner join例子: 在一般写s ...
- 时序分析:串匹配-KMP算法
图像处理与模式识别的教科书使用大量的章节来描述空域的模式识别方法.从图像底层特征提取.贝叶斯方法到多层神经网络方法,一般不讨论到对象随时间变化的情况,视频处理应用和在线学习方法使研究对象开始向时域延伸 ...
- 面试回答问题要防范hr的陷阱
面试技巧是大众化的,比较实在.在经历的各种面试中,最不容易防范的面试就是“拉呱”(山东方言,聊天的意思),这样子自己容易放松警惕. 看看下面的,就知道应该怎么应对这些“滑头”的HR! 1.我们为什么要 ...
- sql 排序
select count(*) from vote group by contents PERCENT * from vote order by contents)as A group by cont ...
- C#—接口和抽象类的区别?
一.接口 接口是指对协定进行定义的引用类型,其他类型实现接口,以保证它们支持某些操作.接口指定必须由类提供的成员或实现它的其他接口.与类相似,接口可以包含方法.属性.索引器和事件作为成员. 1.接口存 ...