题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1059
题目链接:http://poj.org/problem?id=1014
题意:给我们6种物品,其价值分别是1、2、3、4、5、6,给出我们这些物品每一种的数量,问我们可不可以将其分成价值一模一样的两堆。
此题的做法就是运用典型的多重背包问题,最后只需要判断是否满足dp[sum/2] == sum/2就可以了。
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
const int maxn = 20000*6+5;
int dp[maxn],v,n[10];
void ZeroOnePack(int cost,int value)
{for(int i=v; i>=cost; i--)dp[i]=max(dp[i],dp[i-cost]+value);
}
void CompletePack(int cost,int value)
{for(int i=cost; i<=v; i++)dp[i]=max(dp[i],dp[i-cost]+value);
}
void MultiPack(int cost,int value,int num)
{int k;if(num*cost>=v)CompletePack(cost,value);else{k=1;while(num>k){ ZeroOnePack(k*cost,k*value);num-=k;k*=2;}ZeroOnePack(num*cost,num*value);}
}
int main()
{int k = 1;while(scanf("%d",&n[1])!=EOF){int sum = n[1]*1;for(int i=2; i<=6; i++){scanf("%d",&n[i]);sum += n[i]*i;}if(sum==0) break;if(sum&1){printf("Collection #%d:\nCan't be divided.\n\n",k++);continue;}v = sum/2;memset(dp,0,sizeof(dp));for(int i=1; i<=6; i++)MultiPack(i,i,n[i]);if(dp[v] == v)printf("Collection #%d:\nCan be divided.\n\n",k++);else printf("Collection #%d:\nCan't be divided.\n\n",k++);}
}