分析:
如果想要公平的分得弹球,那么弹球的价值总和一定是偶数,可以先进行判断弹球的价值总和,若是奇数则不需要做下面的判断。
如果是偶数,我们可以把这个问题映射为多重背包问题,并且这个背包是要求完全装满的。背包的总容量V就是所有弹球总价值和sum的一半,弹球的cost和weight都是其编号。个数则是由外界输入的。最后进行判断:如果得到的F[V]确定的等于sum/2,则说明能够公平的分弹球。
需要注意的是,由于弹球最大个数是20000,所以极端情况是20000个弹球都是放在了价值为6的位置上,这样,V的最大值就是6*20000/2+1=60001。
好了,翠花,上代码:
#include <iostream>
using namespace std;
#define LEN 7
#define INIT 0xffffffff
int F[60001];
int max(int x, int y)
{
return x>y?x:y;
}
void ZeroOnePack(int cost, int weight, int V)
{
for (int v=V; v>=cost; --v) {
F[v] = max(F[v], F[v-cost]+weight);
}
}
void CompletePack(int cost, int weight, int V)
{
for (int v=cost; v<=V; ++v) {
F[v] = max(F[v], F[v-cost]+weight);
}
}
void MultiPack(int cost, int weight, int V, int amount)
{
if (cost*amount>=V) {
CompletePack(cost, weight, V);
return;
}
int k = 1;
while (k<amount) {
ZeroOnePack(cost*k, weight*k, V);
amount -= k;
k *=2;
}
ZeroOnePack(cost*amount, weight*amount, V);
}
int main(int argc, char **argv)
{
int index = 0;
int num[LEN];
while (1) {
++index;
int sum = 0;
int bin = 0;
for (int i=1; i<LEN; ++i) {
cin>>num[i];
sum += i * num[i];
bin |= num[i];
}
if (!bin)
break;
if (sum&0x01)
cout<<"Collection #"<<index<<":\n"<<"Can't be divided."<<endl<<endl;
else {
int V = sum>>1;
F[0] = 0;
for (int i=1; i<=V; ++i)
F[i] = INIT;
for (int i=1; i<LEN; ++i)
MultiPack(i, i, V, num[i]);
if(F[V]!=V)
cout<<"Collection #"<<index<<":\n"<<"Can't be divided."<<endl<<endl;
else
cout<<"Collection #"<<index<<":\n"<<"Can be divided."<<endl<<endl;
}
}
system("pause");
return 0;
}
0MS过!done!
版权声明:本文为warringah1原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。