题面
题意
给出最多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;
}
}
}
}