HDU 1059 Dividing(多重背包二进制优化)
题意:给你 6 个数,代表 1~6 的数的数量,问你是否能将这堆数分成两组,使他们各自和相等
思路:首先我们可以对整堆数求和,和为 sum ,如果和是奇数,则肯定不对;如果是偶数的话,就将问题转化成能否从这堆数中取若干数,使他们和为 sum/2 。那该问题其实就又转化为了一个容积为 sum/2 的多重背包问题了,如果 g[sum/2] == sum/2 就可以。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<Vector>
#include<cstring>
#define pb push_back
using namespace std;
int g[500005],arr[10];
int main()
{
int ans,sum=0,cnt=1;
while(~scanf("%d%d%d%d%d%d",&arr[1],&arr[2],&arr[3],&arr[4],&arr[5],&arr[6]))
{
memset(g,0,sizeof(g));
sum=0;
for(int i=1; i<=6; i++)
{
sum+=i*arr[i];
}
if(!sum)
break;
printf("Collection #%d:\n",cnt++);
vector<pair<int,int>>goods;
for(int i=1; i<=6; i++)
{
{
for(int k=1; k<=arr[i]; k*=2)
{
arr[i]-=k;
goods.pb({i*k,i*k});
}
if(arr[i]>0)
goods.pb({i*arr[i],i*arr[i]});
}
}
if(sum%2)
printf("Can't be divided.\n\n");
else
{
ans=sum/2;
for(auto i:goods)
{
for(int j=ans; j>=i.first; j--)
{
g[j]=max(g[j],g[j-i.first]+i.second);
}
}
if(g[sum/2]==sum/2)
printf("Can be divided.\n\n");
else
printf("Can't be divided.\n\n");
}
}
return 0;
}
戒骄戒躁,百炼成钢!