HDU 1171 Big Event in HDU 动态规划多重背包
http://acm.hdu.edu.cn/showproblem.php?pid=1171
题意:
给定你每种设备的价值和数量 , 要你将这些设备平分( 就算不是刚好平分也要尽量接近 ) .
坑爹:
一开始看到这题是一点思路都没有 , 以为一定要刚好平分 . 数组要开到 50 * 50 * 100 .
解法:
只要将所有设备的价值加起来(sum) , 然后利用多重背包 , 但"背包"的容量不是sum , 而是
sum/2 , 这样就可以找出当"背包"的容量为总价值一半的时候的最优情况 , 然后另外一边分到的
设备就是 sum - DP[sum/2] .
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 using namespace std; 3 4 const int maxn = 250000 + 10; 5 6 struct computer 7 { 8 int worth; 9 int count; 10 }; 11 12 struct computer A[maxn]; 13 int mid; 14 int DP[maxn]; 15 16 int max(int a,int b) 17 { 18 return a > b ? a : b; 19 } 20 21 void ZeroOnePack(int cost,int weight) 22 { 23 int j; 24 for(j=mid; j>=cost; j--) 25 { 26 DP[j] = max(DP[j] , DP[j-cost]+weight); 27 } 28 } 29 30 void CompletePack(int cost,int weight) 31 { 32 int j; 33 for(j=cost; j<=mid; j++) 34 { 35 DP[j] = max(DP[j] , DP[j-cost]+weight); 36 } 37 } 38 39 void MultiplePack(int cost,int weight,int amount) 40 { 41 if(cost * amount >= mid) 42 { 43 CompletePack(cost,weight); 44 return ; 45 } 46 int k = 1; 47 while(k < amount) 48 { 49 ZeroOnePack(cost*k , weight*k); 50 amount = amount - k; 51 k = k * 2; 52 } 53 ZeroOnePack(amount*cost , amount*weight); 54 } 55 56 int main() 57 { 58 int n; 59 while(cin>>n && n >= 0) 60 { 61 int i; 62 int sum = 0; 63 memset(DP,0,sizeof(DP)); 64 for(i=1; i<=n; i++) 65 { 66 cin>>A[i].worth>>A[i].count; 67 sum += A[i].worth * A[i].count; 68 } 69 mid = sum / 2; 70 71 for(i=1; i<=n; i++) 72 { 73 MultiplePack(A[i].worth,A[i].worth,A[i].count); 74 } 75 76 cout<<sum - DP[mid]<<" "<<DP[mid]<<endl; 77 78 } 79 return 0; 80 }