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;	
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章