NYOJ 546 Divideing Jewels

Divideing Jewels

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 4
描述

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.

这个题是个多重背包的问题

多重背包:

有N种物品,和一个容量为V的背包,第i种物品有Mi件,,每件物品消耗的空间为Ci,价值为Wi,求在不超过背包容量的情况下,所获得最大价值是多少

转换为01背包的问题得到动态转移方程

dp[i][j]=max(dp[i][j-k*Ci]+Wi)  (0<=k<=Mi)

/*
多重背包问题要求很简单,就是每件物品给出确定的件数,求  
可得到的最大价值  
多重背包转换成 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;  
        }  
    }  
  
现在用count 代替 n 就和01 背包问题完全一样了  
*/ 
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#define MAX 100005
using namespace std;
int dp[MAX];
int main(){
	int a[15];
	int t=1;
	while(true){
		int sum=0;
		for(int i=1;i<=10;i++){
			scanf("%d",&a[i]);
			sum+=a[i]*i;
		}
		if(!sum) break;
		int v[105],cont=0;
		//二进制分解 
		for(int i=1;i<=10;i++){
			for(int j=1;j<=a[i];j*=2){
				v[cont++]=j*i;
				a[i]-=j;
			}
			if(a[i]>0){
				v[cont++]=a[i]*i;
				a[i]=0;
			}
		}
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=cont;i++){
			for(int j=sum/2;j>=v[i];j--){
				dp[j]=max(dp[j],dp[j-v[i]]+v[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++);
	}
} 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值