POJ2576【背包】
题意:
每个人必须在一个团队或其他;
人对两支球队的数量不得超过1不同;
人们对各队的总重量应尽可能接近相等越好。
思路:
那么我求一个能接近最接近总和一半的值。
每个人的值就是物品,每个物品有且只有一个,
这里有两种重量,一种是体重不得超过一半,另一种是人数不得超过 n/2,应该是(n+1)/2,我们多给前面的部分机会去增大到最靠近总重的一半;
具体还是0/1背包模型,主要还加了一个判断条件是人数。
那么我们可以用dp[]表示该体重下最少人数,也代表前i个值能够组成的值
#include<cstdio>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=45000;
int dp[N];
int a[110];
int main()
{
int n,sum;
scanf("%d",&n);
sum=0;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
int W=(sum+1)/2;
int m=(n+1)/2;
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int i=0;i<n;i++)
for(int j=W;j>=0;j--)
{
if(dp[j]&&dp[j]<=m) //这里的话因为一开始0的时候就有多了一个人,所以就不需要dp[]+1<=m了,准确地说是dp[]+1<=m+1;一开始wa了
{
if(j+a[i]<=W)
{
if(dp[j+a[i]])
dp[j+a[i]]=min(dp[j+a[i]],dp[j]+1);
else
dp[j+a[i]]=dp[j]+1;
}
}
}
int k;
for(int i=W;i>=0;i--)
{
if(dp[i])
{
k=i;
break;
}
}
printf("%d %d\n",k,sum-k);
}