Tug of War

题目描述

A tug of war is to be arranged at the local office picnic. For the tug of war, the picnickers must be divided into two teams. Each person must be on one team or the other; the number of people on the two teams must not differ by more than 1; the total weight of the people on each team should be as nearly equal as possible.

The first line of input contains n the number of people at the picnic. n lines follow. The first line gives the weight of person 1; the second the weight of person 2; and so on. Each weight is an integer between 1 and 450. There are at most 100 people at the picnic.

Your output will be a single line containing 2 numbers: the total weight of the people on one team, and the total weight of the people on the other team. If these numbers differ, give the lesser first.

假如输入

3
100
90
200

应当输出

190 200

分析:有n个人,要分成2组,每个人有一个体重,要求两组人的总体重尽可能的接近。两个组的人数只差不得超过1.分别输出两个组分好后,人员总体重。总体重小的那个组先输出,中间隔一个空格。典型的01背包动态规划。人数一定,找出最接近中间值的那个数即可。动态转移方程: if(dp[j][k]) dp[j+1][k+wei[i]]=true;

dp[j][k]表示从所有人里面选出j个人能拼成k的总体重;

在j个人能拼出的总体重可以等于k时,那么我们加入第i个人,我们的总人数就是j+1了,这时候拼出的总体重就是k+wei[i]了;

在处理的时候,我们必须从后面往前面搜索k。否则,我们本次处理的前面得出的数据变化会影响到后面的处理。

ac源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cctype>
#include<cmath>
#include<cstring>
#include<queue>
#include<string>
using namespace std;
bool dp[55][22550];
int wei[102];
void solve();
int main()
{
solve();
return 0;
}
void solve()
{
int t,n,sum,i,j,k;
sum=0;
cin>>n;
for(i=0; i<n; i++)
cin>>wei[i],sum+=wei[i];
memset(dp,false,sizeof(dp));
dp[0][0]=true;
for(i=0; i<n; i++)
for(j=n/2; j>=0; j--)
for(k=sum/2-wei[i]; k>=0; k--)
if(dp[j][k])
dp[j+1][k+wei[i]]=true;
int max;
for(i=sum/2; i>=0; i--)
{
if(dp[n/2][i])
{
max=i;
break;
}
}
if(n%2!=0)
{
for(i=sum/2; i>=0; i--)
if(dp[n/2+1][i])
{
if(i>max)
max=i;
break;
}
}
cout<<max<<" "<<sum-max<<endl;
}