LightOJ - 1147 Tug of War

题面

题意

给出最多100个数,将这组数等分为两组(两组的数的个数尽可能接近)。
输出两组数字的和之差最小时,分别输出两组数字的和。
所有数字的和小于等于100000

做法

这题处理比较巧妙,因为每组最多有50个数,可以压在一个long long内,我们可以用dp[i]=j来表示要想质量之和为i,则可以由k个数相加得到,k构成的集合状压为j。即,若j转化为二进制后,第k位上为1,表示i可以由k个数相加得到。
之后用01背包即可解决此问题。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
#define N 100100
using namespace std;

ll T,TT,n,dp[N],num[110],sum,js;

int main()
{
    ll i,j;
    cin>>T;
    TT=T;
    while(T--)
    {
        memset(dp,0,sizeof(dp));
        sum=0;
        scanf("%lld",&n);
        for(i=1; i<=n; i++)
            scanf("%lld",&num[i]),sum+=num[i];
        js=sum;
        sum/=2;
        dp[0]=1;
        for(j=1;j<=n;j++)
        {
            for(i=sum;i>=num[j];i--)
            {
                dp[i]|=(dp[i-num[j]]<<1);
                dp[i]&=(1ll << 60)-1;
            }
        }
        for(i=sum; i>=1; i--)
        {
            if((dp[i]&(1ll << (n/2)) )|| (dp[i]&(1ll << ((n+1)/2))))
            {
                printf("Case %lld: %lld %lld\n",TT-T,i,js-i);
                break;
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/yzyyylx/article/details/80963020
war