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] .

 

View Code
 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 }

 

 

posted @ 2012-09-15 19:22  pc....  阅读(181)  评论(0编辑  收藏  举报