解析:
多重背包模板题
ac:
#include<bits/stdc++.h>
#define MAXN 105
#define inf 0x3f3f3f
#define M 1000005
using namespace std;
int p[MAXN],v[MAXN],num[MAXN];
int dp[M];
void onepack(int m,int v,int w)
{
for(int i=m;i>=v;i--)
dp[i]=max(dp[i],dp[i-v]+w);
}
void compack(int m,int v,int w)
{
for(int i=v;i<=m;i++)
dp[i]=max(dp[i],dp[i-v]+w);
}
void multpack(int m,int v,int w,int num)
{
if(v*num>=m)
{
compack(m,v,w);
return ;
}
int k=1;
for(k=1;k<=num;k<<=1)
{
onepack(m,k*v,k*w);
num=num-k;
}
if(num)
onepack(m,num*v,num*w);
}
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&v[i],&p[i],&num[i]);
memset(dp,0,sizeof(dp));
for(int i=1;i<=m;i++)
multpack(n,v[i],p[i],num[i]);//钱,体积,价值,数目
printf("%d\n",dp[n]);
}
return 0;
}
题意:
给n钟硬币,面值为a[i],数目为c[i]
问可以组成的多少种价值不超过m的情况
解析:
多重背包模板题
多重背包+二进制优化
ac:
#include<bits/stdc++.h>
#define inf 0x3f3f3f
#define MAXN 100005
using namespace std;
int a[MAXN],c[MAXN];
int dp[MAXN];
void onepack(int m,int v,int w)
{
for(int i=m;i>=v;i--)
dp[i]=max(dp[i],dp[i-v]+w);
}
void compack(int m,int v,int w)
{
for(int i=v;i<=m;i++)
dp[i]=max(dp[i],dp[i-v]+w);
}
void multpack(int m,int v,int w,int num)
{
if(v*num>=m)
{
compack(m,v,w);
return ;
}
int k=1;
for(k=1;k<=num;k<<=1)
{
onepack(m,k*v,k*w);
num=num-k;
}
if(num)
onepack(m,num*v,num*w);
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0)
break;
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int i=0;i<n;i++)
scanf("%d",&c[i]);
for(int i=0;i<=m;i++)
dp[i]=-inf;
dp[0]=0;
for(int i=0;i<n;i++)
multpack(m,a[i],a[i],c[i]);
int sum=0;
for(int i=1;i<=m;i++)
if(dp[i]>0)
sum++;
printf("%d\n",sum);
}
return 0;
}
题意:
给6个数,分别代表面值1,2,3,4,5,6硬币的数目
问能否将这些硬币分层相等的两部分.
解析:
多重背包+二进制优化,sum%2==1,直接不能
判断dp[sum/2]==sum/2
ac:
#include<bits/stdc++.h>
#define inf 0x3f3f3f
#define MAXN 500005
using namespace std;
int a[MAXN],c[MAXN];
int dp[MAXN];
void onepack(int m,int v,int w)
{
for(int i=m;i>=v;i--)
dp[i]=max(dp[i],dp[i-v]+w);
}
void compack(int m,int v,int w)
{
for(int i=v;i<=m;i++)
dp[i]=max(dp[i],dp[i-v]+w);
}
void multpack(int m,int v,int w,int num)
{
if(v*num>=m)
{
compack(m,v,w);
return ;
}
int k=1;
for(k=1;k<=num;k<<=1)
{
onepack(m,k*v,k*w);
num=num-k;
}
if(num)
onepack(m,num*v,num*w);
}
int main()
{
int cas=1;
while(1)
{
int sum=0,flag=0;
for(int i=1;i<=6;i++)
{
a[i]=i;
scanf("%d",&c[i]);
sum+=c[i]*a[i];
}
if(!sum)
break;
if(sum%2==0)
{
memset(dp,0,sizeof(dp));
for(int i=1;i<=6;i++)
multpack(sum/2,a[i],a[i],c[i]);
if(dp[sum/2]==sum/2)
printf("Collection #%d:\nCan be divided.\n\n",cas);
else
printf("Collection #%d:\nCan't be divided.\n\n",cas);
}
else{
printf("Collection #%d:\nCan't be divided.\n\n",cas);
}
cas++;
}
return 0;
}