HDU 1171 Big Event in HDU【01背包/求两堆数分别求和以后的差最小】

Big Event in HDU
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 48364 Accepted Submission(s): 16581

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
【题意】:有很多个人,其中每个人有一个自己的权值,权值一共有n种,要分配成两个部分,要尽量保证每个部分的分数尽量接近,并且第一部分的权值要大于等于第二个部分。
【分析】:总代价是背包的一半。经典的求两堆数分别求和以后的差最小,转化为01背包。首先计算总权值sum,以总权值的一半作为背包的容量,由于第二部分的分数恒小于等于总权值一半,把第二部分当作背包模型。又要保证两部分权值要尽量相等,所以把每个人的权值即当做放入背包中的物体的体积,也当做物体的价值,就可以保证第二部分的权值小于第一部分却有尽可能接近第一部分的权值。
【注意】:这道题是以负数作为输入的结束标志的,而不只局限于-1, 被惯性思维坑了。

#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include<stack>
#include<sstream>
#include<list>
#include<assert.h>
#include<bitset>
#include<numeric>
#define debug() puts("++++")
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a,b,sizeof(a))
#define sz size()
#define be begin()
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define rep(i,n,x) for(int i=(x); i<(n); i++)
#define in freopen("in.in","r",stdin)
#define out freopen("out.out","w",stdout)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e18;
const int MAXN =  1e3 + 5;
const int maxm = 1e6 + 10;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int dx[] = {-1,1,0,0,1,1,-1,-1};
const int dy[] = {0,0,1,-1,1,-1,1,-1};
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int n,m;
int a,b;
int c[maxm];
int v[maxm], w[maxm],dp[maxm];
int main()
{
    int n,k,sum;
    while(cin>>n, n>0){
        k=sum=0;
        memset(c,0,sizeof(c));
        memset(dp,0,sizeof(dp));

        for(int i=0;i<n;i++){
        cin>>a>>b;
        while(b--){
               c[k++]=a;
               sum+=a;
            }
        }

        for(int i=0; i<k; i++){
            for(int j=sum/2; j>=c[i]; j--){
                dp[j] = max(dp[j],dp[j-c[i]]+c[i]);
            }
        }
        cout<<sum-dp[sum/2]<<' '<<dp[sum/2]<<endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Roni-i/p/9054937.html