样例输入:
1 0 1 2 0 0
1 0 0 0 1 1
0 0 0 0 0 0
样例输出:
Collection #1:
Can't be divided.
Collection #2:
Can be divided.
题意:一开始给你6种物品的数量,每种物品的价值分别1~6,问你能否找到一种方案使得价值均分(不能将物品拆开)
分析:这是一道多重背包问题,我们判断是否能将价值均分不就等价于能否找到一种情况使得物品价值和是总价值的一半吗?题目中又给了我们每种物品的数量,所以我们可以用二进制优化一下,不会二进制优化的小伙伴可以看下这里:(POJ-1276)Cash Machine(二进制优化+多重背包)_AC__dream的博客-CSDN博客
我们的背包的价值和体积是对等的,所以不妨假设所有物品的总价值为sum,我们最后判断可行解的条件就是判断f[sum/2]==sum/2是否成立即可
下面是代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int N=100003;
int f[N],v[N];
int a[10];
int main()
{
int _=0;
while(scanf("%d%d%d%d%d%d",&a[1],&a[2],&a[3],&a[4],&a[5],&a[6])&&(a[1]||a[2]||a[3]||a[4]||a[5]||a[6]))
{
_++;
int sum=0;
for(int i=1;i<=6;i++) sum+=a[i]*i;
if(sum&1)
{
printf("Collection #%d:\n",_);
printf("Can't be divided.\n\n");
continue;
}
memset(f,0,sizeof f);
int cnt=0;
for(int i=1;i<=6;i++)
{
for(int j=1;j<=a[i];j<<=1)
{
v[++cnt]=j*i;
a[i]-=j;
}
if(a[i]) v[++cnt]=a[i]*i;
}
sum>>=1;
for(int i=1;i<=cnt;i++)
for(int j=sum;j>=v[i];j--)
f[j]=max(f[j],f[j-v[i]]+v[i]);
if(f[sum]==sum)
{
printf("Collection #%d:\n",_);
printf("Can be divided.\n\n");
}
else
{
printf("Collection #%d:\n",_);
printf("Can't be divided.\n\n");
}
}
return 0;
}