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 }

 

 

转载于:https://www.cnblogs.com/pcpcpc/archive/2012/09/15/2686881.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值