zoukankan      html  css  js  c++  java
  • [POJ 1014] Dividing

    问题描述

    Marsha and Bill own a collection of marbles. They want to split the collection among themselves so that both receive an equal share of the marbles. This would be easy if all the marbles had the same value, because then they could just split the collection in half. But unfortunately, some of the marbles are larger, or more beautiful than others. So, Marsha and Bill start by assigning a value, a natural number between one and six, to each marble. Now they want to divide the marbles so that each of them gets the same total value. Unfortunately, they realize that it might be impossible to divide the marbles in this way (even if the total value of all marbles is even). For example, if there are one marble 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 marbles.

    输入格式

    Each line in the input file describes one collection of marbles to be divided. The lines contain six non-negative integers n1 , . . . , n6 , where ni is the number of marbles of value i. So, the example from above would be described by the input-line "1 0 1 2 0 0". The maximum total number of marbles will be 20000.
    The last line of the input file will be "0 0 0 0 0 0"; do not process this line.

    输出格式

    For each collection, output "Collection #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
    1 0 0 0 1 1
    0 0 0 0 0 0

    样例输出

    Collection #1:
    Can't be divided.

    Collection #2:
    Can be divided.

    题意概括

    给定六种硬币,第i种硬币的价值为i,输入每种硬币的数量ni,判断这些硬币能否分成价值相同的两组。

    解析

    首先,如果硬币的价值(sum)总数不是2的倍数,那么无论如何都无法分成价值相同的两组,直接输入即可。否则,每组的价值总数就是(sum/2)。那么问题就转化为已知硬币的数量和价值,从中选出一些硬币,问能否使这些硬币的价值综合为(sum/2)(如果一组为(sum/2),那么另一组也肯定为(sum/2))。这显然就可以用多重背包的方法来实现了。将这个背包的容积设为(sum/2),每个硬币的价值和体积都为自己的价值,最后只需要判断总体积为(sum/2)时总价值是否也为(sum/2)即可。

    另外,因为数量特别庞大,这里的多重背包需要使用二进制优化。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define N 1000000
    #define M 1000000
    using namespace std;
    int n,w,i,j,c[N],v[N],num[N],nc[N],nv[N],ncnt,sum,f[M],cnt;
    int main()
    {
    	for(i=1;i<=6;i++) c[i]=i;
    	while(1){
    		cnt++;
    		sum=ncnt=0;
    		memset(f,0,sizeof(f));
    		for(i=1;i<=6;i++){
    			cin>>num[i];
    			sum+=num[i]*i;
    		}
    		if(sum==0) break;
    		cout<<"Collection #"<<cnt<<":"<<endl;
    		if(sum%2==1){
    			cout<<"Can't be divided."<<endl<<endl;
    			continue;
    		}
    		else w=sum/2;
    		for(i=1;i<=6;i++){
    			int k;
    			for(k=1;num[i]-(1<<k)+1>0;k++){
    				ncnt++;
    				nc[ncnt]=(1<<(k-1))*c[i];
    			}
    			ncnt++;
    			k--;
    			nc[ncnt]=(num[i]-(1<<k)+1)*c[i];
    		}
    		for(i=1;i<=ncnt;i++){
    			for(j=w;j>=nc[i];j--){
    				f[j]=max(f[j],f[j-nc[i]]+nc[i]);
    			}
    		}
    		if(f[w]!=w) cout<<"Can't be divided."<<endl;
    		else cout<<"Can be divided."<<endl;
    		cout<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    《梦幻西游》打响反盗号战役:为2亿玩家提供360安全武器 狼人:
    瑞星发表官方声明:记者王学武系恶意诽谤 狼人:
    中美联合挫败Conficker蠕虫大攻击 狼人:
    安全机构建议奥巴马政府谨慎使用开源软件 狼人:
    大量计算机遭“灰鸽子”病毒攻击 狼人:
    警惕IE7新漏洞导致的木马病毒暴增 狼人:
    IE7漏洞被瞄准 新型攻击将爆发 狼人:
    Windows 7成为Pwn2own黑客挑战赛目标 狼人:
    黑客入侵唱片业协会网站 为“海盗湾”助威 狼人:
    “猫癣”“犇牛”木马病毒肆虐 专家提醒补漏洞 狼人:
  • 原文地址:https://www.cnblogs.com/LSlzf/p/10804615.html
Copyright © 2011-2022 走看看