zoukankan      html  css  js  c++  java
  • codevs 3269 混合背包 如题(二进制优化)

    3269 混合背包

     

     时间限制: 1 s
     空间限制: 256000 KB
     题目等级 : 钻石 Diamond
     
     
     
     
    题目描述 Description

    背包体积为V ,给出N个物品,每个物品占用体积为Vi,价值为Wi,每个物品要么至多取1件,要么至多取mi件(mi > 1) , 要么数量无限 , 在所装物品总体积不超过V的前提下所装物品的价值的和的最大值是多少?

    输入描述 Input Description

    第一行两个数N,V,下面N行每行三个数Vi,Wi,Mi表示每个物品的体积,价值与数量,Mi=1表示至多取一件,Mi>1表示至多取Mi件,Mi=-1表示数量无限

    输出描述 Output Description

    1个数Ans表示所装物品价值的最大值

    样例输入 Sample Input

    2 10

    3 7 2

    2 4 -1

    样例输出 Sample Output

    22

    数据范围及提示 Data Size & Hint

    对于100%的数据,V <= 200000 , N <= 200

    ------------------------------------------------------------------------------------------------------------------------

    看题目就知道是混合背包模板题

    这里的多重背包不能用三个for,即不能够直接把每件物品的数量展开变成01背包,会T,需要用二进制拆分优化

    简单地讲一下自己对于二进制拆分的理解吧

    用二进制拆分的方法,也是将多重背包转化为01背包,但我们不是一个一个地去枚一种物品的数量,而是把这个物品的数量按二进制拆分成几个数。例如物品的数量为7,体积为v,价值为w,则7的二进制为111,就可以把7拆成 001 010 100 ,即1 2 4,这样就能把这中数量为7的物品拆分成3种数量为1的物品,分别为 v1=1*v,w1=1*w ; v2=2*v,w2=2*w ; v3=4*v,w3=4*w。

    为什么能这样拆呢?

    因为这样拆之后的选择可以囊括所有组合

    还是以上面的例子

    把7(111)拆成001 010 100之后,这三个数可以组合成任意小于等于7的自然数。

    详细看代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<iostream>
     4 #define maxn 233333
     5 using namespace std;
     6 int read();
     7 void zeropack(int,int);
     8 void compack(int,int);
     9 void multpack(int,int,int);
    10 int n,V,dp[maxn];
    11 int main(){
    12     n=read(),V=read();
    13     for(int i=1;i<=n;i++){
    14         int v=read(),w=read(),num=read();
    15         if(num==1) zeropack(v,w);
    16         else if(num==-1) compack(v,w);
    17         else multpack(v,w,num);
    18     }
    19     printf("%d",dp[V]);
    20     return 0;
    21 }
    22 void zeropack(int v,int w){
    23     for(int i=V;i>=v;i--)
    24     dp[i]=max(dp[i],dp[i-v]+w);
    25 }
    26 void compack(int v,int w){
    27     for(int i=v;i<=V;i++)
    28     dp[i]=max(dp[i],dp[i-v]+w);
    29 }
    30 void multpack(int v,int w,int num){
    31     if(num*v>=V){
    32         compack(v,w);
    33         return;
    34     }
    35     int k=1;
    36     while(k<num){
    37         zeropack(v*k,w*k);
    38         num-=k;
    39         k<<=1;
    40     }
    41     if(num>0) zeropack(num*v,num*w);
    42 }
    43 int read(){
    44     int ans=0,f=1;char c=getchar();
    45     while('0'>c||c>'9'){if(c=='-')f=-1;c=getchar();}
    46     while('0'<=c&&c<='9')ans=ans*10+c-48,c=getchar();return ans*f;
    47 }
    混合背包(二进制优化)
  • 相关阅读:
    redis 学习笔记三
    hadoop 家族图
    hbase 笔记
    spark history server
    利用Intellij IDEA构建spark开发环境
    自己安装的工具版本
    hive读书笔记
    数据仓库元数据
    Spark RDD
    pg mysql 比较
  • 原文地址:https://www.cnblogs.com/lpl-bys/p/7648073.html
Copyright © 2011-2022 走看看