HDU 1059-Dividing

Dividing

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 27758    Accepted Submission(s): 7973


题目链接:点击打开链接



Problem Description
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.
 

Input
Each line in the input describes one collection of marbles to be divided. The lines consist of six non-negative integers n1, n2, ..., 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.
 

Output
For each colletcion, 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.


Sample Input
1 0 1 2 0 0
1 0 0 0 1 1
0 0 0 0 0 0
 


Sample Output
Collection #1:
Can't be divided.


Collection #2:
Can be divided.




题意:
有一堆玻璃球,他们的价值从 1 到 6,现在有两个人想平分这些价值的玻璃球,每种玻璃球有一定的数量,但是每个玻璃珠是不能被拆分的,所以很多情况下,他们可能并不能平分这些玻璃珠 ,给出你每一种价值的玻璃珠的数量,让你判断他们是否可以得到相同价值的玻璃珠。


分析:
多重背包,本来之前学长讲过多重背包,理解的不是很好,而且他给出的模板是背包九讲里的模板,我从网上看到别人的不同的二进制优化方法,感觉要比那个模板好一些,但一直 wa ,本题我 wa 了 15 次,心塞,但最终在还是找出了错误,是一些细节上的小错误,在这里就不细说了,多重背包我感觉就是二进制优化加上 01 背包




#include 
#include
#include
#include
#include
using namespace std;

int dp[60005];
int v1[60005],w1[60005];

int main()
{
    int bj=0;
    int v[10]={1,2,3,4,5,6};///存价值
    int ans[10];
    while(~scanf("%d %d %d %d %d %d",&ans[0],&ans[1],&ans[2],&ans[3],&ans[4],&ans[5]))
    {
        if(ans[0]+ans[1]+ans[2]+ans[3]+ans[4]+ans[5]==0)
            break;
        bj++;
        int k=0;
        int sum,half;
        sum=ans[0]*v[0]+ans[1]*v[1]+ans[2]*v[2]+ans[3]*v[3]+ans[4]*v[4]+ans[5]*v[5];
        printf("Collection #%d:\n",bj);
        if(sum%2!=0)///如果这些物品不能被正着平分,说明肯定不行
        {
            printf("Can't be divided.\n");
            printf("\n");
            continue;
        }
        half=sum/2;///背包的容量就是所有物品价值的一半
        for(int i=0;i<6;i++)///进行二进制优化
        {
            for(int j=1;j<=ans[i];j*=2)
            {
                v1[k++]=j*v[i];
                ans[i] -= j;
            }
            if(ans[i] > 0)///这个点要好好理解理解
                v1[k++]=ans[i]*v[i];
        }
        memset(dp,0,sizeof(dp));///和01背包一样 将dp刷为1
        for(int i=0;i=v1[i];j--)
                   dp[j]=max(dp[j],dp[j-v1[i]]+v1[i]);
        if(dp[half]==(sum/2))
            printf("Can be divided.\n");
        else
            printf("Can't be divided.\n");
        printf("\n");
    }
    return 0;
}






你可能感兴趣的:(ACM-多重背包)