问是否平分N的物品的价值
先求出N个物品的价值总和
如何是奇数,则一定不能平分
如果是偶数,则half = total/2
既题目转化为给定多重背包的N个物品,为是否能装满half的背包,如果可以,则可以平分。
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
#define MAX_V (6+1)
#define MAX_F (1000000+1)
//#define printf //
int Amount[MAX_V];
bool F[MAX_F];
int n=6,m;
void ZeroOnePack(int value)
{
//printf("zero one pack value:%d\n",value);
for(int v=m;v>=value;--v)
{
F[v] |= F[v-value];
// printf("F[%d] = %d\n",v,F[v]);
}
}
void CompletePack(int value)
{
for(int v=value;v<=m;v++)
F[v] |= F[v-value];
}
void MultiPack(int value,int amount)
{
if(value * amount >= m)
{
CompletePack(value);
return;
}
int k=1;
while(k<amount)
{
ZeroOnePack(value * k);
amount -= k;
k <<= 1;
}
if(amount)
ZeroOnePack(value*amount);
}
int main()
{
int k=1;
while(true)
{
bool iFound = false;
int total = 0,half;
int ret = 0;
memset(F,0,sizeof(F));
F[0]=true;
for(int i=1;i<MAX_V;i++)
{
cin >> Amount[i];
//printf("i=%d Amount[%d]=%d\n",i,i,Amount[i]);
if(Amount[i] != 0)
iFound = true;
total += i * Amount[i];
}
if(!iFound)
break;
if(total % 2 != 0)
ret = 0;
else
{
half = total/2;
m = half;
for(int i=1;i<MAX_V;i++)
if(Amount[i])
MultiPack(i,Amount[i]);
if(F[m])
ret = 1;
}
printf("Collection #%d:\n",k++);
if(ret)
printf("Can be divided.\n");
else
printf("Can't be divided.\n");
printf("\n");
}
}