如题:http://poj.org/problem?id=1014
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 62483 | Accepted: 16183 |
Description
Input
The last line of the input file will be "0 0 0 0 0 0"; do not process this line.
Output
Output a blank line after each test case.
Sample Input
1 0 1 2 0 0 1 0 0 0 1 1 0 0 0 0 0 0
Sample Output
Collection #1: Can't be divided. Collection #2: Can be divided.
Source
题目大意:有6种物品,价值是(1,2,3,4,5,6),分别给出他们的数量,问能否价值平分。
思路:等价于一个容量为所有石头总价值(V)的背包,装入这些石头,求f[V/2]==V/2?
f[i]代表当前背包容量是i时能装入的石头所能产生的最大价值。
如果f[V/2]==V/2?
代表正好平分,否则不能,还有就是如果V是奇数,肯定不能平分
注意每一个例子答案输出下面要输出空的一行
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define max(a,b)(a>b?a:b)
int num[7];
int f[500000]; //f[i]代表装入背包的石头总价值是i时所能表示实际最大价值。
int sum=0; //总容量
void CompletePack(int c,int w)
{
int i;
for(i=c;i<=sum;i++)
f[i]=max(f[i],f[i-c]+w);
}
void ZeroOnePack(int c,int w)
{
int i;
for(i=sum;i>=c;i--)
f[i]=max(f[i],f[i-c]+w);
}
void MultiplePack(int c,int w,int n)
{
if(c*n>=sum)
{
CompletePack(c,w);
return;
}
int k=1;
while(k<n)
{
ZeroOnePack(k*c,k*w);
n-=k;
k*=2;
}
ZeroOnePack(c*n,w*n);
}
int main()
{
// freopen("C:\\1.txt","r",stdin);
int cas=0;
while(~scanf("%d%d%d%d%d%d",&num[1],&num[2],&num[3],&num[4],&num[5],&num[6]))
{
memset(f,0,sizeof(f));
if(!num[1]&&!num[2]&&!num[3]&&!num[4]&&!num[5]&&!num[6])
break;
cas++;
sum=num[1]+num[2]*2+num[3]*3+num[4]*4+num[5]*5+num[6]*6;
if(sum%2)
{
printf("Collection #%d:\nCan't be divided.\n\n",cas);
continue;
}
int i;
for(i=1;i<=6;i++)
MultiplePack(i,i,num[i]);
if(f[sum/2]==sum/2)
printf("Collection #%d:\nCan be divided.\n\n",cas);
else
printf("Collection #%d:\nCan't be divided.\n\n",cas);
}
return 0;
}