动态规划:混合背包

我们首先来介绍一下多重背包是什么

可以这样理解:01背包≤多重背包≤完全背包

01背包每种物品最多选一件

完全背包每种物品可以选无数件,但受限制于背包的容量

多重背包每种物品可以选的件数是给出的,同样也受限制于背包的容量

多重背包在实现的时候可以进行二进制优化,大致思路是放多件的情况可以进行拆分成几种放少件的情况,之前放少件的情况已经考虑过了,放多件的情况就不用考虑这些拆出来的情况了

接下来我们引出混合三种背包的问题

每种物品可以放1件,可以放无限件,也可以放若干件,问背包所能放物品的最大的价值

我们给出01和完全背包的实现:

int f[maxv];
void zpack(int v0,int w0)
{
    for(int i=V;i>=v0;i--)
        f[i]=max(f[i],f[i-v0]+w0);
}
void cpack(int v0,int w0)
{
    for(int i=v0;i<=V;i++)
        f[i]=max(f[i],f[i-v0]+w0);
}

接下来考虑多重背包的情况,用2进制方法拆成01去处理,拆不出来的再放一次

for(int j=1;j<=m[i];j*=2)
            {
                zpack(v[i]*j,w[i]*j);
                m[i]-=j;
            }
            zpack(m[i]*v[i],m[i]*w[i]);

这样我们的问题解决了,下面给出完整的实现,物品数无限本题是用-1来表示的

 1 #include<iostream>
 2 #include<algorithm> 
 3 using namespace std;
 4 const int maxv=200005,maxn=205;
 5 int N,V;
 6 int v[maxn],w[maxn],m[maxn];
 7 long long ans=0;
 8 //
 9 int f[maxv];
10 void zpack(int v0,int w0)
11 {
12     for(int i=V;i>=v0;i--)
13         f[i]=max(f[i],f[i-v0]+w0);
14 }
15 void cpack(int v0,int w0)
16 {
17     for(int i=v0;i<=V;i++)
18         f[i]=max(f[i],f[i-v0]+w0);
19 }
20 int main()
21 {
22     cin>>N>>V;
23     for(int i=1;i<=N;i++)
24         cin>>v[i]>>w[i]>>m[i];
25     for(int i=1;i<=N;i++)
26     {
27         if(m[i]==-1||m[i]*v[i]>V)
28             cpack(v[i],w[i]);
29         else
30         {
31             for(int j=1;j<=m[i];j*=2)
32             {
33                 zpack(v[i]*j,w[i]*j);
34                 m[i]-=j;
35             }
36             zpack(m[i]*v[i],m[i]*w[i]);
37         }
38     }
39     ans=f[V];
40     cout<<ans<<endl;
41     return 0;
42 }

 

posted @ 2018-07-14 10:03  静听风吟。  阅读(187)  评论(0编辑  收藏  举报