zoukankan      html  css  js  c++  java
  • 题解报告:hdu 1171 Big Event in HDU(多重背包)

    Problem Description

    Nowadays, we all know that Computer College is the biggest department in HDU. But, maybe you don't know that Computer College had ever been split into Computer College and Software College in 2002.
    The splitting is absolutely a big event in HDU! At the same time, it is a trouble thing too. All facilities must go halves. First, all facilities are assessed, and two facilities are thought to be same if they have the same value. It is assumed that there is N (0<N<1000) kinds of facilities (different value, different kinds).

    Input

    Input contains multiple test cases. Each test case starts with a number N (0 < N <= 50 -- the total number of different facilities). The next N lines contain an integer V (0<V<=50 --value of facility) and an integer M (0<M<=100 --corresponding number of the facilities) each. You can assume that all V are different.
    A test case starting with a negative integer terminates input and this test case is not to be processed.

    Output

    For each case, print one line containing two integers A and B which denote the value of Computer College and Software College will get respectively. A and B should be as equal as possible. At the same time, you should guarantee that A is not less than B.

    Sample Input

    2
    10 1
    20 1
    3
    10 1
    20 2
    30 1
    -1

    Sample Output

    20 10
    40 40
    解题思路:典型的多重背包问题,由于题目给的时限比较多,果断转化成01背包暴力过了233。题意是:尽量使得A,B两者分得的价值接近相等(两者价值总和为所有设施设备的总价值),并且A分得的价值不小于B分得的价值,那么问题就可以转化成不超过总价值的一半(视为背包的容量△(已经是确定值))下,挑选若干件物品装入背包后,使得总价值最大,即为B得到的最大价值,A得到的价值为sum-dp[sum/2]。最坏的时间复杂度大约为6e8级别,可见测试数据挺水的。
    AC代码一(717ms):
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,v,m,num,sum,vi[5005],dp[125005];//最大价值的一半:50*100*50/2=125000,数组开大一点即可
     4 int main(){
     5     while(~scanf("%d",&n)&&n>=0){
     6         memset(vi,0,sizeof(vi));
     7         memset(dp,0,sizeof(dp));
     8         num=sum=0;//sum记录总价,num记录物品的总数
     9         while(n--){
    10             scanf("%d%d",&v,&m);
    11             while(m--){//有m个价值相等的物品
    12                 vi[num++]=v;//把m个物品看成m件不同的物品,多重背包转化成01背包
    13                 sum+=v;//累加价值
    14             }
    15         }
    16         for(int i=0;i<num;++i)
    17             for(int j=sum/2;j>=vi[i];--j)
    18                 dp[j]=max(dp[j],dp[j-vi[i]]+vi[i]);
    19         printf("%d %d
    ",sum-dp[sum/2],dp[sum/2]);//dp[sum/2]比较小即为B,因为求解过程是让max尽量靠近sum/2
    20     }
    21     return 0;
    22 }

    AC代码二(78ms):

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int t,W,n,tol,value[55],num[55],dp[125005];
     4 void ZeroOnePack(int w,int v){//01背包
     5     for(int j=W;j>=w;--j)
     6         dp[j]=max(dp[j],dp[j-w]+v);
     7 }
     8 void CompletePack(int w,int v){//完全背包
     9     for(int j=w;j<=W;++j)
    10         dp[j]=max(dp[j],dp[j-w]+v);
    11 }
    12 void MultiplePack(int w,int v,int num){//多重背包
    13     if(w*num>=W)CompletePack(w,v);
    14     else{
    15         for(int k=1;k<=num;k<<=1){//二进制思想
    16             ZeroOnePack(w*k,v*k);
    17             num-=k;
    18         }
    19         if(num>0)ZeroOnePack(w*num,v*num);
    20     }
    21 }
    22 int main(){
    23     while(~scanf("%d",&n)&&n>=0){
    24         memset(dp,0,sizeof(dp));tol=W=0;
    25         for(int i=1;i<=n;++i){
    26             scanf("%d%d",&value[i],&num[i]);
    27             tol+=value[i]*num[i];
    28         }
    29         W=tol/2;
    30         for(int i=1;i<=n;++i)
    31             MultiplePack(value[i],value[i],num[i]);
    32         printf("%d %d
    ",tol-dp[W],dp[W]);
    33     }
    34     return 0;
    35 }

    AC代码三(62ms):单调队列优化

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int W,n,tol,val[55],num[55],dp[125005];
     4 struct node{
     5     int k,v;
     6     node(int x,int y):k(x),v(y){}
     7 };
     8 deque<node> dq;
     9 void SingleDeque(int w,int v,int cnt){
    10     for(int r=0;r<w;++r){//r=j%w
    11         dq.clear();
    12         for(int t=0;t*w+r<=W;++t){//t=j/w
    13             int tmp=dp[t*w+r]-t*v;
    14             while(!dq.empty()&&tmp>=dq.back().v)dq.pop_back();
    15             dq.push_back(node(t,tmp));
    16             while(!dq.empty()&&(t-cnt>dq.front().k))dq.pop_front();
    17             dp[t*w+r]=dq.front().v+t*v;
    18         }
    19     }
    20 }
    21 int main(){
    22     while(~scanf("%d",&n)&&n>=0){
    23         tol=W=0;memset(dp,0,sizeof(dp));
    24         for(int i=1;i<=n;++i)
    25             scanf("%d%d",&val[i],&num[i]),tol+=val[i]*num[i];
    26         W=tol/2;
    27         for(int i=1;i<=n;i++){
    28             num[i]=min(num[i],W/val[i]);
    29             SingleDeque(val[i],val[i],num[i]);
    30         }
    31         printf("%d %d
    ",tol-dp[W],dp[W]);
    32     }
    33     return 0;
    34 }
  • 相关阅读:
    图文描述Vs2005制作WEB应用程序安装包的方法[E8.Net正式用户可以找我们获取全部代码参考]
    20080517 ITIL本地化实施沙龙活动记录
    制作 类似 google 下拉框的用户自定义控件的实现思路
    SQL SERVER 2005 Reporting Services 部署报表管理站点在 有主机头的站点上时的处理方法
    五月 我们都是四川人
    通过VML技术 及 XSLT技术实现WEB图形化处理界面.
    工作流技术杂谈 2008
    Visual Studio 2005 通过静态变量及可系列化的HASHTABLE变量优化工厂模式(Factory)的效率,提升性能(E8.Net工作流应用系统优化系列四)
    2008年4月21日 QQ群关于服务级别管理的聊天记录,欢迎加入ITIL与服务管理新QQ群:58342347
    Tapestry5之Application Module
  • 原文地址:https://www.cnblogs.com/acgoto/p/9522601.html
Copyright © 2011-2022 走看看