题目大意

给出几组物品的体积和价值,每组分为三种: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 混合背包的更多相关文章

  1. HDU 3535 AreYouBusy(混合背包)

    HDU3535 AreYouBusy(混合背包) http://acm.hdu.edu.cn/showproblem.php?pid=3535 题意: 给你n个工作集合,给你T的时间去做它们.给你m和 ...

  2. UESTC 424 AreYouBusy --混合背包

    混合三种背包问题. 定义:dp[i][k]表示体积为k的时候,在前i堆里拿到的最大价值. 第一类,至少选一项,dp初值全赋为负无穷,这样才能保证不会出现都不选的情况.dp[i][k] = max(dp ...

  3. HDU 3535 AreYouBusy (混合背包)

    题意:给你n组物品和自己有的价值s,每组有l个物品和有一种类型: 0:此组中最少选择一个 1:此组中最多选择一个 2:此组随便选 每种物品有两个值:是需要价值ci,可获得乐趣gi 问在满足条件的情况下 ...

  4. HDU 3535 分组混合背包

    http://acm.hdu.edu.cn/showproblem.php?pid=3535 题意:有n组工作,T时间,每个工作组中有m个工作,改组分类是s,s是0是组内至少要做一件,是1时最多做一件 ...

  5. Codevs 3269 混合背包(二进制优化)

    3269 混合背包 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description 背包体积为V ,给出N个物品,每个物品占用体积为V ...

  6. HDU3535——AreYouBusy

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3535 题目意思:给出两个数n,T,分别表示有n个任务集合,T的总时间,对于每个任务集合有两个属性m和t ...

  7. codevs 3269 混合背包(复习混合背包)

    传送门 [题目大意]给出物品的数量.-1为无限个. [思路]混合背包.... [code] #include<iostream> #include<cstdio> #inclu ...

  8. [codevs3269]混合背包

    题目大意:一道混合背包模板. 解题思路:分三种情况讨论,01和完全没什么问题,多重背包需要把物品分成$\log W[i]$件,然后01即可,分成W[i]件01会TLE. 读优大法好! C++ Code ...

  9. CODE[VS] 3269 混合背包

    3269 混合背包  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description 背包体积为V ,给出N ...

随机推荐

  1. php统计网站 / html页面 浏览访问次数程序

    本文章来给大这介绍了php自己写的一些常用的网站统计代码写法,用无数据库的与使用数据库及html静态页面浏览资次数统计代码,大家可进入参考. 实例1 直接使用txt文件进行统计的代码 <?php ...

  2. 代码code设置9.png/9-patch 图片背景后,此view中的TextView等控件显示不正常

    代码code设置9.png/9-patch 图片背景后,此view中的TextView等控件显示不正常 设置 padding=0

  3. SQlserver 当输入参数为可选条件

    以前很懒,都是用拼接字符串的方式,加上if 语句,根据输入参数是否为空来判断是否需要在where 后加上对应字段的条件限制 但是拼接字符串很烦,又总是被转义符搞得很烦  '''' 所以想了其他办法 分 ...

  4. 初次尝试PHP——一个简单的对数据库操作的增删改查例子

    第一次学习PHP,很多人说PHP是最好的语言,学习了一点点,还不敢说这样的话,不过确实蛮好用的. 做了一个简单的对数据库的增删改查的操作,主要是将四种操作写成了独立的函数,之后直接调用函数.以下是代码 ...

  5. 浅谈Java三大框架与应用

    前言:对于一个程序员来说,尤其是在java web端开发的程序员,三大框架:Struts+Hibernate+Spring是必须要掌握熟透的,因此,下面谈谈java三大框架的基本概念和原理. JAVA ...

  6. HTML基础知识总结(一)

    概述       HTML是将内容和内容显示形式结合在一起的语言,它对于内容显示形式的控制,主要是通过标签(元素)的属性,由于它对“内容显示形式”存在着很多的弊端,所以之后就出现了CSS,CSS就相当 ...

  7. Sobel算子取代:基于特定点方向的canny边缘检测

    前言: Canny边缘检测使用了Sobel算子,计算dx和dy两个方向,对于特定方向的边缘检测,可以作少量修改. 代码: 计算特定方向上的边缘 void CannyOrient( cv::Mat &a ...

  8. 【sqli-labs】 less28a GET- Blind based -All you Union&Select Belong to us -String -Single quote-parenthesis(GET型基于盲注的去除了Union和Select的单引号带括号字符型注入)

    和less28没什么区别,直接上个payload吧 http://192.168.136.128/sqli-labs-master/Less-28a/?id=0')%a0uNion%a0sElect% ...

  9. Memcached 之缓存雪崩现象、实际案例和缓存无底洞现象

    一.缓存雪崩现象 由于集群中某个memcached服务器宕机的原因,造成集群中的服务器命中率下降.只能通过访问数据库得到数据,是的数据库的压力倍增,造成数据库服务器崩溃.重启数据库还是会崩溃,但是数据 ...

  10. Jquery隐藏和显示Div的控制

    html页面代码: <input type="checkbox" name="searchType" value="searchNews&quo ...