题意:有n个人,每个人都由重量。现将其分成人数差小于等于1的两组,求两组各自总质量之差最小的组合。
题解:动态规划,dp[i]=m,其中i为重量,m为二进制,其第k位为1表示可以由k个人组合使得总质量为i。之后就是01背包了。
耗时:588MS/4000MS
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define LL __int64
const LL maxn=5e4+10;
LL dp[maxn];//dp[i]=m,表示重量为i的可由m种方式。m种方式是用50位的二进制数表示,第k位为1表示可以由k个人组成质量为i。
LL a[111];
bool judge(LL x,LL n)
{
if(n%2==0)
{
n=n/2;
if(x&(1LL<<n))return true;//注意1LL,64位的
return false;
}
else
{
n=n/2;
if((x&(1LL<<n))||(x&(1LL<<(n+1))))return true;
return false;
}
}
int main()
{
LL T,tt=0;
cin>>T;
while(T--)
{
LL i,j,k,m,sum=0,n;
cin>>n;
for(i=0;i<n;i++)
{
cin>>a[i];
sum+=a[i];
}
m=sum/2;
memset(dp,0,sizeof(dp));
dp[0]=1;
for(i=0;i<n;i++)
{
for(j=m;j>=a[i];j--)
dp[j]=dp[j]|(dp[j-a[i]]<<1);
}
//for(i=0;i<=m;i++)
// cout<<i<<" "<<dp[i]<<endl;
for(i=m;i>=0;i--)
{
if(judge(dp[i],n))
{
cout<<"Case "<<++tt<<": "<<i<<" "<<sum-i<<endl;
break;
}
}
}
return 0;
}