HDU 1059 Dividing 多重背包动态规划
http://acm.hdu.edu.cn/showproblem.php?pid=1059
题意:
给出价值分别为1-6的东西 , 输入代表价值为1-6的个数 , 现在问你将这些东西完全平分成两份 , 看能不能
刚好平分.
坑爹:
我一开始是想用多重背包算出 DP[sum] 然后在看下 DP[sum/2] 是不是刚好是sum的一半 , 但这样会超时
解法:
用多重背包 把背包的 "体积" 定为总价值的一半就是行了 , 不需要算到 "体积" 为sum .

1 #include<iostream> 2 using namespace std; 3 const int maxn = 120000 + 10; 4 int DP[maxn]; 5 int sum; 6 7 int max(int a,int b) 8 { 9 return a > b ? a : b; 10 } 11 12 void ZeroOnePack(int cost,int weight) 13 { 14 int j; 15 for(j=sum/2; j>=cost; j--) 16 { 17 DP[j] = max(DP[j] , DP[j-cost]+weight); 18 } 19 } 20 21 void CompletePack(int cost,int weight) 22 { 23 int j; 24 for(j=cost; j<=sum/2; j++) 25 { 26 DP[j] = max(DP[j] , DP[j-cost]+weight); 27 } 28 } 29 30 void MultiplePack(int cost,int weight,int amount) 31 { 32 if(cost * amount >= sum/2) 33 { 34 CompletePack(cost,weight); 35 return ; 36 } 37 int k = 1; 38 while(k<amount) 39 { 40 ZeroOnePack(k*cost,k*weight); 41 amount = amount - k; 42 k = k * 2; 43 } 44 ZeroOnePack(amount*cost,amount*weight); 45 } 46 47 int main() 48 { 49 int k=1; 50 int num[6]; 51 while(cin>>num[0]>>num[1]>>num[2]>>num[3]>>num[4]>>num[5],num[0]+num[1]+num[2]+num[3]+num[4]+num[5]) 52 { 53 memset(DP,0,sizeof(DP)); 54 printf("Collection #%d:\n",k++); 55 int i; 56 sum = 0; 57 for(i=0; i<6; i++) 58 { 59 sum += ( (i + 1) * num[i] ); 60 } 61 if(sum%2) 62 { 63 cout<<"Can't be divided."<<endl<<endl; 64 continue; 65 } 66 for(i=0; i<6; i++) 67 { 68 MultiplePack(i+1,i+1,num[i]); 69 } 70 if(DP[sum/2] == sum/2) 71 { 72 cout<<"Can be divided."<<endl; 73 } 74 else 75 { 76 cout<<"Can't be divided."<<endl; 77 } 78 cout<<endl; 79 } 80 return 0; 81 }