hdu 1059 Dividing
题目描述
输入描述:
输出描述:
示例1
输入
1 0 1 2 0 0
1 0 0 0 1 1
0 0 0 0 0 0
输出
Collection #1:
Can't be divided.
Collection #2:
Can be divided.
题意:
有价值分别是1~6的6种大理石,每种大理石的数量是ni,问能否将这些大理石分成完全相同的两部分?
题解:
这个题和hdu 2844 Coins做法基本一样,不过本题要稍微转变下思路
我们考虑用背包方法来做,题目给了数量,价值,却没有给总容量和体积。我们结合题意思考一下,要分成价值完全相同的两份,其实就是找到一份大理石,使得这一份的价值是总价值的一半。如果我们这样想,我们就会发现,总容量其实就是大理石总价值的一半,每个大理石的体积就是其价值,我们要做的就是找到“一些商品使得其体积满足总容量一半的情况是否存在”,这不就可以用混合背包来做。
对于数量多的用完全背包,对于数量少的用多重背包
代码:
#include<bits/stdc++.h>
using namespace std;
int a[8];
int sum=0;
int dp[120005];
bool f=0;;
void zerone(int cost,int val)
{
for(int i=sum;i>=cost;i--)
{
dp[i]=max(dp[i],dp[i-cost]+val);
}
}
void complet(int cost)
{
for(int i=cost;i<=sum;i++)
dp[i]=max(dp[i],dp[i-cost]+cost);
}
void mul(int cost,int val,int num)
{
if(cost*num>=sum)
{
complet(cost);
return ;
}
for(int i=1;i<=num;i<<=1)
{
zerone(i*cost,i*val);
num-=i;
}
zerone(num*cost,num*val);
}
int main()
{
int case1=0;
while(cin>>a[1]>>a[2]>>a[3]>>a[4]>>a[5]>>a[6])
{
case1++;
f=0;
memset(dp,0,sizeof(dp));
if(a[1]==0&&a[2]==0&&a[3]==0&&a[4]==0&&a[5]==0&&a[6]==0)break;
printf("Collection #%d:\n",case1);
sum=a[1]*1+2*a[2]+3*a[3]+4*a[4]+5*a[5]+6*a[6];
if(sum%2)
{
printf("Can't be divided.\n");
printf("\n");
continue;
}
sum/=2;
for(int i=1;i<=6;i++)
{
mul(i,i,a[i]);//花费,价值,数量
}
if(dp[sum]==sum)f=1;
if(f==1)cout<<"Can be divided."<<endl;
else cout<<"Can't be divided."<<endl;
cout<<endl;
}
return 0;
}