文章目录
混合背包

简单来说就是多重背包与完全背包的混合,也就是说既存在可以无限获取的物品,也存在获取上限的物品
基本思想
这道题其实也就看着复杂,其实就是把三种背包问题放一起了。我们来分析一下,上面讲多重背包的时候,通过二进制优化,将多重背包分解为01背包来写,那么现在就变成了两种背包问题混合了,那么怎么处理呢?
可以将多重背包用二进制优化成01背包,然后再做一遍01背包与完全背包就行了
代码
cpp
#include<bits/stdc++.h>
using namespace std;
int a[100100],b[100100],c[100100],v,w,s,m,n,cnt=0,f[100100];
int main()
{
cin>>m>>n;
for(int i=1;i<=m;i++)
{
cin>>v>>w>>s;
if(s==0)
{
a[++cnt]=v;
b[cnt]=w;
c[cnt]=s;
}
else
{
if(s==-1)
s=1;
for(int j=1;j<=s;j*=2)
{
a[++cnt]=v*j;
b[cnt]=w*j;
c[cnt]=1;
s-=j;
}
if(s>0)
{
a[++cnt]=v*s;
b[cnt]=w*s;
c[cnt]=1;
}
}
}
for(int i=1;i<=cnt;i++)
{
if(c[i])
{
for(int j=n;j>=a[i];j--)
f[j]=max(f[j],f[j-a[i]]+b[i]);
}
else
{
for(int j=a[i];j<=n;j++)
f[j]=max(f[j],f[j-a[i]]+b[i]);
}
}
cout<<f[n]<<endl;
return 0;
}
分组背包
问题描述
给定n nn个物品,以及一个容量大小为m mm的背包,然后给出n nn个物品的体积及价值,n个物品是分为若干组,每组最多只能选择一个物品。求背包最大价值是多少,也就是选择总体积不超过m mm的物品,然后使总价值最大。
基本思想
朴素代码
cpp
#include<bits/stdc++.h>
using namespace std;
int v[1010][1010],w[1010][1010],f[1010][1010],m,n,a,b,t[1010];
int main()
{
cin>>m>>n;
for(int i=1;i<=m;i++)
{
cin>>t[i];
for(int j=1;j<=t[i];j++)
{
cin>>a>>b;
v[i][j]=a,w[i][j]=b;
}
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=0;k<=t[i];k++)
{
if(v[i][k]<=j)
f[i][j]=max(f[i][j],f[i-1][j-v[i][k]]+w[i][k]);
}
}
}
cout<<f[m][n]<<endl;
return 0;
}
优化代码
cpp
#include<bits/stdc++.h>
using namespace std;
int v[1010][1010],w[1010][1010],f[1010],m,n,a,b,t[1010];
int main()
{
cin>>m>>n;
for(int i=1;i<=m;i++)
{
cin>>t[i];
for(int j=1;j<=t[i];j++)
{
cin>>a>>b;
v[i][j]=a,w[i][j]=b;
}
}
for(int i=1;i<=m;i++)
{
for(int j=n;j>=1;j--)
{
for(int k=0;k<=t[i];k++)
{
if(v[i][k]<=j)
f[j]=max(f[j],f[j-v[i][k]]+w[i][k]);
}
}
}
cout<<f[n]<<endl;
return 0;
}