hdu-1059(多重背包+二进制优化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1059
题意:输入6个数,每个数ni代表价值为i的物品有ni个。求如果这些物品能均分给两个人,每个人获得的物品的总价值
相同,就输出“Can be divided.”,否则输出“Can't be divided.”;具体格式见输出格式。
思路:本来想用dfs做的,后来发现时间超限了,其实可以用多重背包来做,
每个物品的数量有限,找出是否存在几个物品的价值与物品总价值的一半相同。
参考文章:https://blog.csdn.net/aaaaacmer/article/details/48543575
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int dp[100100],a[20],sum; void f(int cost,int num) { int i; if(cost*num>=sum) { for(i=cost;i<=sum;i++) dp[i]=max(dp[i],dp[i-cost]+cost); return ; } int k=1; while(k<num) { for(i=sum;i>=k*cost;i--) dp[i]=max(dp[i],dp[i-cost*k]+cost*k); num-=k; k*=2; } for(i=sum;i>=num*cost;i--) dp[i]=max(dp[i],dp[i-cost*num]+cost*num); } int main(void) { int pt=1,i,j; while(cin>>a[1]>>a[2]>>a[3]>>a[4]>>a[5]>>a[6]) { if(!a[1]&&!a[2]&&!a[3]&&!a[4]&&!a[5]&&!a[6]) break; sum=0; for(i=1;i<=6;i++) sum+=a[i]*i; printf("Collection #%d:\n",pt++); if(sum%2) { printf("Can't be divided.\n\n"); continue; } sum/=2; memset(dp,0,sizeof(dp)); for(i=1;i<=6;i++) f(i,a[i]); if(dp[sum]==sum) printf("Can be divided.\n\n"); else printf("Can't be divided.\n\n"); } return 0; }