您的位置:首页 > 其它

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

2016-05-28 10:07 225 查看

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: