poj 1014
题意:给出6个数,分别表示面值为1-6对应钱币的数量。判断是否可以等值分割总金额。
分析:多重背包应用。计算出总金额sum,若为奇数,则false,否则sum/=2;背包容量即为此时的sum,费用和价值相同,求出dp[sum].判断dp[sum]==sum?true:false.
注意点:因为物品要装满背包,所以初始化dp数组,dp[1……n]=负无穷,dp【0】=0;
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define NN 20000*6
#define INF_MIN -0xfffff
const int l=6;
#define loop(i,k,n) for(i=k;i<=n;i++)
int dp[NN],num[8],va[]={0,1,2,3,4,5,6};
void ZeroOne_Package(int value,int weight,int m)
{
for(int j=m;j>=weight;j--)
dp[j]=max(dp[j],dp[j-weight]+value);
}
void Complete_Package(int value,int weight,int m)
{
for(int j=weight;j<=m;j++)
dp[j]=max(dp[j],dp[j-weight]+value);
}
void Multiply_Package(int *v,int *w,int m,int n)
{
for(int i=1;i<=n;i++){
if(num[i]*w[i]>m)
Complete_Package(v[i],w[i],m);
else{
int k=1;
while(k<=num[i])
{
ZeroOne_Package(k*v[i],k*w[i],m);
num[i]-=k;
k<<=1;
}
ZeroOne_Package(num[i]*v[i],num[i]*w[i],m);
}
}
}
int main()
{
int i,k=1;
while(k)
{
int sum=0,flag=0;
loop(i,1,6)
scanf("%d",num+i),sum+=i*num[i],flag|=num[i];
if(!flag)
break;
printf("Collection #%d:\n",k++);
if(sum&1)
puts("Can't be divided.\n");
else{
sum>>=1;
loop(i,1,sum)
dp[i]=INF_MIN; dp[0]=0;
Multiply_Package(va,va,sum,l);
//printf("dp[sum]= %d\n",dp[sum]);
if(dp[sum]!=sum)
puts("Can't be divided.\n");
else
puts("Can be divided.\n");
}
}
return 0;
}
hdu 2844
题意 : n种钱币,金额cash .给出每种金币的数量及其面值 ,求不超过cash的可以价值 数。
分析:多重背包,和上面一题一样,没啥区别,同一模板=_=
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define NN 100000+2
int dp[NN],num[1002],va[102];
#define loop(i,k,n) for(i=k;i<=n;i++)
#define loop2(i,k,n) for(i=n;i>=k;i--)
const int INF_MIN=-0xffffff;
void Zero(int v,int w,int m)
{
int j;
loop2(j,w,m)
dp[j]=max(dp[j],dp[j-w]+v);
}
void Complete(int v,int w,int m)
{
int j;
loop(j,w,m)
dp[j]=max(dp[j],dp[j-w]+v);
}
void Multiply(int *v,int *w,int m,int n)
{
int i,j,k;
loop(i,1,n)
{
if(num[i]*w[i]>m)
Complete(v[i],w[i],m);
else{
k=1;
while(k<=num[i]){
Zero(k*v[i],k*w[i],m);
num[i]-=k;
k<<=1;
}
Zero(num[i]*v[i],num[i]*w[i],m);
}
}
}
int main()
{
int n,m,i;
while(scanf("%d%d",&n,&m),n&&m)
{
int Count=0;
loop(i,1,n) scanf("%d",va+i);
loop(i,1,n) scanf("%d",num+i);
loop(i,1,m) dp[i]=INF_MIN;
dp[0]=0;
Multiply(va,va,m,n);
loop(i,1,m)
if(dp[i]==i)
Count++;
printf("%d\n",Count);
}
}