原题链接
一道混合背包模板题,题目如下
题解:
将多重背包采取二进制优化,将三类背包问题分为只有01背包和完全背包,[目的:将时间复杂度从O(NVS)优化到O(NVlogS)] 然后判断背包类型采取不同dp方式
时间复杂度:O(NVlogS)
参考代码如下(有注释)
/*********************************************************************/
/**********************************cyf*******************************/
/*******************************************************************/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,x) for(int i=0;i<x;i++)
#define ll long long
#define repp(i,x) for(int i=1;i<=x;i++)
#define repx(i,n,j) for(int i=j;i<n;i++)
const ll mod=1e9+7;
bool shushu(int x)
{
int flag=0;
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
flag=1;
break;
}
}
if(flag)
return false;
else
return true;
}
int gcd(int x,int y)
{
int t;
while(y%x!=0)
{
t=y%x;
y=x;
x=t;
}
return x;
}
int lcm(int x,int y)
{
return x/gcd(x,y)*y;
}
ll q_pow(ll a,ll b,int m)//
{
ll r=1,base=a;
while(b!=0){
if(b%2)
r*=base;
r%=m;
base*=base;
base%=m;
b/=2;
}
return r;
}
const int maxn=1e4+5;
int n,m,dp[maxn],w[maxn],v[maxn],s[maxn];
int main()
{
cin>>n>>m;//物品种数和背包容积
int ant=0;//优化后的物品种类数
int x,y,z;
for(int i=1;i<=n;i++)
{
cin>>x>>y>>z;
if(z>1)//多重背包
{
//二进制优化
for(int j=1;j<=z;j*=2)
{
w[++ant]=j*x;
v[ant]=j*y;
s[ant]=1;
z-=j;
}
if(z>0)
{
w[++ant]=z*x;
v[ant]=z*y;
s[ant]=1;
}
}
else// 01背包和完全背包 不做处理
{
w[++ant]=x;
v[ant]=y;
s[ant]=z;
}
}
for(int i=1;i<=ant;i++)
{
if(s[i]==0)//完全背包
{
for(int j=w[i];j<=m;j++)
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
}
else//01背包
{
for(int j=m;j>=w[i];j--)
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
}
}
cout<<dp[m]<<endl;
return 0;
}