HDU 1059 Dividing (多重背包模板题,条件改变,比较灵活)

 

 

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1059

 
 
这道题刚一看,确实没有想到是背包类型的题目,那么我们怎么分析它是一道多重背包问题呢?
首先可以知道的是,我们要将这些硬币分为价值等同的两份
那么,我们可以用sum存下总价值,将总价值当做背包的容量
这样我们用一半的的容量背包去装一半价值的弹珠
当然,如果能装的下,则剩下的一半背包当然能装下另一半价值的弹珠
这里由于弹珠个数有限制有价值有容量所以我们使用多重背包。
 
 
AC代码:
套的是多重背包模板,这个是个人认为比较好理解的模板。
动态方程其实就是10背包,完全背包的模板。
最重要的是多重背包的二进制处理。
如果您还不太清楚,可以浏览下网上传的 背包9讲。
 
#include<iostream>
#include<stdio.h>
using namespace std;
int num[7];
int sum;
int dp[100000];
int max(int a,int b)
{
	if(a>b)
		return a;
	else
		return b;
}
void ZeroOnePack(int cost,int weight)
{
	int i;
 	for(i=sum;i>=cost;i--)
          dp[i]=max(dp[i],dp[i-cost]+weight);
}
void CompletePack(int cost,int weight)
{
	int i;
	for(i=cost;i<=sum;i++)
		dp[i]=max(dp[i],dp[i-cost]+weight);

}
void MultiplePack(int cost,int weight,int amount)
{
	if(cost*amount>=sum)
	{
		CompletePack(cost,weight);

	}
	else
	{
		int k=1;
		while(k<=amount)
		{
			ZeroOnePack(k*cost,k*weight);
			amount-=k;
			k<<=1;  //*2
		}
		ZeroOnePack(amount*cost,amount*weight);
	}
}
int main()
{
	int i;
	int Case=1;
	while(1)
	{
		memset(dp,0,sizeof(dp));
		memset(num,0,sizeof(num));
		sum=0;
		for(i=1;i<=6;i++)
		{
			scanf("%d",&num[i]);
			sum+=num[i]*i;
		}
		if(sum==0)
			break;
		printf("Collection #%d:\n",Case++);
		if(sum%2==1)
		{
			printf("Can't be divided.\n\n");
			continue;
		}
		sum/=2;
		for(i=1;i<=6;i++)
		{
			if(num[i]==0)
				continue;
			MultiplePack(i,i,num[i]);

		}
		if(dp[sum]!=sum)			 //转为为给你一半容量的包能否装一半价值的物品。
			printf("Can't be divided.\n\n");
		else
			
			printf("Can be divided.\n\n");

	}
	
	
	return 0;
}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值