nyoj 546 Divideing Jewels 第五届河南省程序设计大赛

Divideing Jewels

描述

Mary and Rose own a collection of jewells. They want to split the collection among themselves so that both receive an equal share of the jewels. This would be easy if all the jewels had the same value, because then they could just split the collection in half. But unfortunately, some of the jewels are larger, or more beautiful than others. So, Mary and Rose start by assigning a value, a natural number between one and ten, to each jewel. Now they want to divide the jewels so that each of them gets the same total value. Unfortunately, they realize that it might be impossible to divide the jewels in this way (even if the total value of all jewels is even). For example, if there are one jewel of value 1, one of value 3 and two of value 4, then they cannot be split into sets of equal value. So, they ask you to write a program that checks whether there is a fair partition of the jewels.

输入
Each line in the input file describes one collection of jewels to be divided. The lines contain ten non-negative integers n1 , . . . , n10 , where ni is the number of jewels of value i. The maximum total number of jewells will be 10000. 
The last line of the input file will be "0 0 0 0 0 0 0 0 0 0"; do not process this line. 
输出
For each collection, output "#k:", where k is the number of the test case, and then either "Can be divided." or "Can't be divided.". 
Output a blank line after each test case. 
样例输入
1 0 1 2 0 0 0 0 2 0
1 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0
样例输出
#1:Can't be divided.#
2:Can be divided.


多重背包问题要求很简单,就是每件物品给出确定的件数,求可得到的最大价值  


多重背包转换成 01 背包问题就是多了个初始化,把它的件数C 用分解成若干个件数的集合,这里面数字可以组合成任意小于等于C的件数,而且不会重复,

之所以叫二进制分解,是因为这样分解可以用数字的二进制形式来解释  


比如:7的二进制 7 = 111 它可以分解成 001 010 100 这三个数可以组合成任意小于等于7 的数,而且每种组合都会得到不同的数 
           15 = 1111 可分解成 0001  0010  0100  1000 四个数字  
如果13 = 1101 则分解为 0001 0010 0100 0110 前三个数字可以组合成 7以内任意一个数,加上 0110 = 6 可以组合成任意一个大于6 小于13的数,虽然有重复但总是能把 13 以内所有的数都考虑到了,基于这种思想去把多件物品转换为,多种一件物品,就可用01 背包求解了。  
看代码: 

 
    int n;  //输入有多少种物品  
    int c;  //每种物品有多少件  
    int v;  //每种物品的价值  
    int s;  //每种物品的尺寸  
    int count = 0; //分解后可得到多少种物品  
    int value[MAX]; //用来保存分解后的物品价值  
    int size[MAX];  //用来保存分解后物品体积  
  
    scanf("%d", &n);    //先输入有多少种物品,接下来对每种物品进行分解  
  
    while (n--) {   //接下来输入n中这个物品  
        scanf("%d%d%d", &c, &s, &v);  //输入每种物品的数目和价值  
        for (int k=1; k<=c; k<<=1) { //<<右移 相当于乘二  
            value[count] = k*v;  
            size[count++] = k*s;  
            c -= k;  
        }  
        if (c > 0) {  
            value[count] = c*v;  
            size[count++] = c*s;  
        }  
    }  
  

#include<stdio.h>
#include<string.h>
#define max(a,b) a>b?a:b
int a[15],b[105];
int dp[100005];
int main(){
	int t=0;
	while(1){
		int sum=0,k=0;
		for(int i=1;i<=10;i++){
			scanf("%d",&a[i]);
			sum+=a[i]*i;
		}
		if(sum==0) break;
		for(int i=1;i<=10;i++){
			for(int j=1;j<=a[i];j<<=1){
				b[k++]=j*i;
				a[i]-=j;
			}
			if(a[i]>0){
				b[k++]=a[i]*i;
				a[i]=0;
			}	
		}
		memset(dp,0,sizeof(dp));
		
		for(int i=0;i<k;i++){
			for(int j=sum/2;j>=b[i];j--)
			dp[j]=max(dp[j],dp[j-b[i]]+b[i]);
		}
		
		if(dp[sum/2]*2==sum) printf("#%d:Can be divided.\n\n",++t);
		else printf("#%d:Can't be divided.\n\n",++t);
	}	
	return 0;	
}





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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值