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);
}
posted @ 2016-08-18 23:56  see_you_later  阅读(193)  评论(0编辑  收藏  举报