HDU--1059 Dividing(多重背包)
2013-12-04 11:28 gongti 阅读(151) 评论(0) 编辑 收藏 举报
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1059
分析:有一堆石头2个人按照其价值均分,石头的价值分为六个等级1,2,3,4,5,6
每一个等级有n[i]个石头也可能一个石头也没有。于是两个人按照总价值进行均分。
因为每一个等级的石头个数是不等的n[i],这是一个多重背包的问题。可以将背包的容量
看成是一个总价值的二分之一。并且要求装满。
#include<stdio.h>
const int INF=0XFFFFFF;
int V,dp[120005];
//01背包
void ZeroOnePack(int cost,int weight)
{
for(int i=V;i>=cost;i--)
dp[i]=dp[i]>dp[i-cost]+weight?dp[i]:dp[i-cost]+weight;
}
//完全背包
void CompletePack(int cost,int weight)
{
for(int i=cost;i<=V;i++)
dp[i]=dp[i]>dp[i-cost]+weight?dp[i]:dp[i-cost]+weight;
}
//多种背包
void MultiplePack(int cost,int weight,int amount)
{
if(cost*amount>=V)
{
CompletePack(cost,weight);
return;
}
int k=1;
while (k<=amount)
{
ZeroOnePack(k*cost,k*weight);
amount-=k;
k*=2;
}
ZeroOnePack(amount*cost,amount*weight);
}
int main()
{
int n[7],sum,k=1;;
while (1)
{
sum=0;
for(int i=1;i<=6;i++)
{
scanf("%d",&n[i]);
sum+=i*n[i];
}
if(!n[1]&&!n[2]&&!n[3]&&!n[4]&&!n[5]&&!n[6]) break;
printf("Collection #%d:\n",k++);
//总价值必须是偶数,否则无法均分
if(sum&1) printf("Can't be divided.\n\n");
else
{
//初始化
V=sum/2;
for(int i=0;i<=V;i++)
dp[i]=-INF;
dp[0]=0;
//多重背包
for(int i=1;i<=6;i++)
MultiplePack(i,i,n[i]);
if(dp[V]>0)
printf("Can be divided.\n\n");
else
printf("Can't be divided.\n\n");
}
}
return 0;
}