zoukankan      html  css  js  c++  java
  • HDU 1171 Big Event in HDU (多重bool背包) /(01背包)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1171

    Big Event in HDU

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 16791    Accepted Submission(s): 5908


    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背包,背包的体积就是总和的一半,然后我们要尽可能的把背包放满:网上有大牛用母函数写的,比较一下差别:

    Run ID Submit Time Judge Status Pro.ID Exe.Time Exe.Memory Code Len. Language Author
    8310536 2013-05-15 Accepted 1171 31MS 392K 1295 B G++ 大牛的
    8310472 2013-05-15 Accepted 1171 2125MS 1332K 837 B G++ 我的

    那时间和内存开销差距!!!

    我的解题代码:

     1 // File Name: Big Event in HDU 1171.cpp
     2 // Author: sheng
     3 // Created Time: 2013年05月15日 星期三 19时53分07秒
     4 
     5 #include <stdio.h>
     6 #include <iostream>
     7 #include <string.h>
     8 using namespace std;
     9 
    10 const int max_n = 5010;
    11 int dp[250005];//数组大小50×100×50
    12 int va[max_n];
    13 
    14 int main ()
    15 {
    16     int n, t, v;
    17     int sum;
    18     while (~scanf ("%d", &n) && n >= 0)
    19     {
    20         sum = 0;
    21         int cun = 0;
    22         memset (dp, 0, sizeof (dp));
    23         while (n--)
    24         {
    25             scanf ("%d %d", &v, &t);
    26             for (int i = 0; i < t; i ++)
    27             {
    28                 va [cun++] = v;
    29             }
    30             sum += v*t;
    31         }
    32         for (int i = 0; i < cun; i ++)
    33         {
    34             for (int j = sum/2; j >= va[i]; j --)
    35             {
    36                 dp[j] = max (dp[j], dp[j-va[i]] + va[i]);
    37             }
    38         }
    39         printf ("%d %d\n", sum - dp[sum/2], dp[sum/2]);
    40     }
    41     return 0;
    42 }
    View Code G++

    大牛的代码:(以后再来理解) 模型:给出n个数,从中选出若干个数相加得到一个新数,求新数的集合

     1 #include<iostream>
     2 #include<stdio.h>
     3 using namespace std;
     4 
     5 //可以看作有a[i]张i元钱,i=1..n;尽量把它们分成相差最小的两份
     6 //f[i]表示可否凑出i元,若有k元且f[i]==1->f[i+k]==1,因为只有一个转移状态,且状态可以叠加(不用清空再来),所以不必用2个数组,可以从后往前更新,
     7 //若从前往后找有些更新的状态会干扰以后的状态 
     8 const int N = 50;
     9 
    10 bool f[250000/2+1];
    11 
    12 int money[N+1],ge[N+1];
    13 
    14 int main()
    15 {
    16     int i,j,k,n,m,total,keep_total;
    17     while(scanf("%d", &n), n >= 0)
    18     {
    19         total = 0;
    20         for(i = 1; i <= n; i ++) 
    21         { 
    22             scanf("%d%d", money+i, ge+i); 
    23             total += money[i] * ge[i];
    24         }
    25         keep_total = total;
    26         total = total/2;         //若前半部分可以凑出,那么后半部分肯定可以,所以只要考虑前半部分就行了 
    27         for(i = 1; i <= total; i++)
    28             f[i] = 0;
    29         f[0] = 1;
    30         for( k = 1; k <= n; k ++)// 多少类
    31         {
    32             for(j = 1; j * 2 - 1 <= ge[k]; j = j * 2)   //每类几件,优化:只需让循环中取得的若干个j之和刚好可以表示从1..ge[k]的每个数,不可多一个,故用2进制 
    33             {
    34                 for(i = total; i >= j * money[k]; i--)
    35                     f[i] |= f[i - j*money[k]];
    36             }
    37             j = ge[k] - (j-1);   //剩下的 
    38             if( j > 0)
    39             {
    40                 for(i = total; i >= j * money[k]; i--)
    41                     f[i] |= f[i-j*money[k]];
    42             }
    43         }
    44         for(i = total; i >= 0; i --)
    45         {
    46             if( f[i] ) 
    47             {
    48                 cout<<keep_total-i<<' '<<i<<endl;
    49                 break;
    50             }
    51         }
    52     }
    53     return 0;
    54 }
    View Code G++
  • 相关阅读:
    (一)Python装饰器的通俗理解
    Linux实例安装VNC Server实现图形化访问
    TightVNC for Windows
    使用Xmanager远程CentOS 7服务器(XDMCP)
    Using Xmanager to connect to remote CentOS 7 via XDMCP
    在windows上使用xdmcp登陆centos,红帽linux
    Xmanger远程连接Centos7(成功配置)
    Centos7.2命令安装图形化界面
    CentOS 7安装图形界面
    CentOS 7命令行安装GNOME、KDE图形界面(成功安装验证)
  • 原文地址:https://www.cnblogs.com/shengshouzhaixing/p/3080853.html
Copyright © 2011-2022 走看看