zoukankan      html  css  js  c++  java
  • 混合背包问题

    题目

    有n种物品和一个容积为V的背包,第i种物品有amount[i]个,体积cost[i]和价值valum[i],问如何选取物品使得放入背包的物品价值之和最大。

    未知具体是 01背包、完全背包还是多重背包

    优化

    • amount[i]==1时,当01背包处理。
    • amount[i]×cost>=V时,当完全背包处理。
    • amount[i]≥1时,采用二进制拆分,从而转换成01背包求解,具体如下:
      在上面的状态转移方程中,我们让k从1→→amount[i]来实现拿不同的个数,从而转换成01背包问题,但我们可以发现,我们只要将amount[i]拆分成几个数,就可以用他们组合成小于amount[i]的任何数。例如:amount[i]=11,11的二进制为1011,把11拆成100(4)、0010(2)、0001(1)、4(11-4-2-1),这样就可以用4、2、1、4来组合成11以内所有的整数,这样放第这种物品时本来放11次,现在只要放4次,虽然仍然有重复,但也实现了优化。

    初始化

    • 如果题目没有要求必须装满,那么我们只要将dp数组全部置为0即可。
    • 如果必须装满,我们就将dp[0]初始化为0,其他初始化为−∞。

    代码

    #include<iostream>
    #include<algorithm>  
    #include<string.h>  
    #include<string>   
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    using namespace std;
    #define CRL(a) memset(a,0,sizeof(a))
    #define M 100000000
    typedef unsigned long long LL;
    typedef  long long ll;
    const int mod =1e9+7;
    
    int V,dp[120002];
    
    void ZeroOnePack(int cost,int valum)		//01背包问题
    {
        for(int i=V;i>=cost;i--)
            dp[i]=max(dp[i],dp[i-cost]+valum);
        return; 
    }
    
    void CompletePack(int cost,int valum)		//完全背包问题
    {
        for(int i=cost;i<=V;i++)
            dp[i]=max(dp[i],dp[i-cost]+valum);
        return;
    }
    
    void MultiplePack(int cost,int valum,int amount)	//多重背包问题
    {
        if(cost*amount>=V)//注意这里!!!!!!!!!!!!!!!!!
            //如果总容量比这个物品的容量要小,那么这个物品可以直到取完,相当于完全背包
            CompletePack(cost,valum);
        else
        {
            int k=1;
            while(k<amount)
            {
                ZeroOnePack(cost*k,valum*k);//这里要调用01背包,但是要乘k
                amount-=k;
                k=k<<1; 	//k*=2
            }
            ZeroOnePack(cost*amount,valum*amount);//最后剩余一个amount
         }
        return; 
    }
    
    int main()
    {
        int n,cost[1000],valum[1000],amount[1000];
        while(cin>>n>>V)
        {
            CRL(dp);
            for(int i=1;i<=n;i++)
                cin>>cost[i]>>valum[i]>>amount[i];
            
            for(int i=1;i<=n;i++)
                MultiplePack(cost[i],valum[i],amount[i]);
            
            cout<<dp[V]<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    chown
    chmod
    商务部
    使用 UEditor 编辑器获取数据库中的数据
    Java实现 蓝桥杯 算法提高 双十一抢购
    Java实现 蓝桥杯 算法提高 双十一抢购
    Java实现 蓝桥杯 算法提高 双十一抢购
    IDEA,PyCharm系列软件常用快捷键
    IDEA,PyCharm系列软件常用快捷键
    IDEA,PyCharm系列软件常用快捷键
  • 原文地址:https://www.cnblogs.com/Jason66661010/p/12788630.html
Copyright © 2011-2022 走看看