zoukankan      html  css  js  c++  java
  • AC日记——Dividing poj 1014

    Dividing
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 69575   Accepted: 18138

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

    Output

    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.

    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.

    Source

     
    题目大意:
      有很多很多的物品,但是总数不过20000。
      然后每个物品的价值在1~6之间
      很多组数据
      每组数据分别输出价值为1~6的物品的个数
      然后叫你判断是否能被分成价值为两堆的物品
     
    思路:
      背包dp,难的一比、、
      这我提交了有4遍才过,两遍tle,一遍pre
      这题坑很多
      读完题后,很多人可能认为这是一道搜索题
      然后开始暴力搜索,最后tle成**。
      我们来分析一下这道题的解法
      首先,它要你把物品分成两堆,而且价值要相等
      所以,我们就有了一个优化
      当物品总价值%2==1时,判定为不能均分
      如果%2==0的话
      我们开始dp
      这个dp是一个裸的多重背包dp
      我们用当前物品的价值推所有价值的是否存在
      价值为i的物品当前层次由价值为i-1的物品当前层次推出
      然后判断物品总价值/2的价值是否存在就好了
      因为物品总价值/2能被凑出来,那么另一半肯定也能
      反之则不能
      但是有点坑
      如果你真的是这样顺着跑了下来,可能会超时
      所以我们要在dp的过程中判定是否有物品总价值/2存在
      这样的一个小优化就不会超时就能ac了
      感觉应该还有更好的解法,但是我想不出来了。、、。
      还有一点
      就是我的一遍pre
      要注意,每组数据之间有一个换行
     
    来,上代码:
    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    int a[7],sum_value=0,ci[7][20001],now=0;
    
    bool dp[7][120000];
    
    bool Check_Answer()
    {
        memset(dp,false,sizeof(dp));
        dp[0][0]=true;
        for(int i=1;i<=6;i++)
        {
            for(int j=0;j<=sum_value;j++)
            {
                if(dp[i][sum_value]) return true;
                if(dp[i-1][j])
                {
                    for(int v=0;v<=a[i];v++) dp[i][j+ci[i][v]]=true;
                }
            }
        }
        if(dp[6][sum_value]) return true;
        else return false;
    }
    
    int main()
    {
        bool if_break;
        while(1)
        {
            if_break=true,sum_value=0,now++;
            for(int i=1;i<=6;i++)
            {
                scanf("%d",&a[i]);
                if(a[i]) if_break=false;
                sum_value+=a[i]*i;
                for(int j=1;j<=a[i];j++) ci[i][j]=i*j;
            }
            if(if_break) break;
            if(sum_value%2)
            {
                printf("Collection #%d:
    Can't be divided.
    
    ",now);
                continue;
            }
            sum_value/=2;
            if(Check_Answer()) printf("Collection #%d:
    Can be divided.
    
    ",now);
            else printf("Collection #%d:
    Can't be divided.
    
    ",now);
        }
        return 0;
    }

    另附我的一个失败代码:

    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    int a[7],sum_value,num,ci[20001],flag;
    
    bool dp[70000];
    
    int main()
    {
        int now=0;
        while(1)
        {
            now++;
            memset(dp,false,sizeof(dp));
            sum_value=0,num=0,flag=1;
            bool if_break=true;
            for(int i=1;i<=6;i++)
            {
                scanf("%d",&a[i]);
                sum_value+=a[i]*i,num+=a[i];
                if(a[i]!=0)
                {
                    if_break=false;
                    for(int j=flag;j<flag+a[i];j++) ci[j]=i;
                    flag+=a[i];
                }
            }
            if(if_break) break;
            if(sum_value%2)
            {
                printf("Collection #%d:
    Can't be divided.
    
    ",now);
                continue;
            }
            sum_value/=2;
            int max_now=0;
            dp[0]=true;
            for(int i=1;i<=num;i++)
            {
                int max_now_=max_now;
                for(int j=0;j<=max_now;j++)
                {
                    if(dp[j])
                    {
                        dp[j+ci[i]]=true;
                        if(j+ci[i]==sum_value)
                        {
                            printf("Collection #%d:
    Can be divided.
    
    ",now);
                            if_break=true;
                            break;
                        }
                        if(j+ci[i]>max_now_&&j+ci[i]<=sum_value) max_now_=j+ci[i];
                    }
                }
                max_now=max_now_;
                if(if_break) break;
            }
            if(if_break) continue;
            printf("Collection #%d:
    Can't be divided.
    
    ",now);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 黑色星期五
    Java实现 蓝桥杯VIP 算法训练 比赛安排
    Java实现 蓝桥杯VIP 算法训练 比赛安排
    Java实现 蓝桥杯VIP 算法训练 斜率计算
    Java实现 蓝桥杯VIP 算法训练 斜率计算
    Java实现 蓝桥杯VIP 算法训练 整数平均值
    Java实现 蓝桥杯VIP 算法训练 整数平均值
    控件动态产生器(使用RegisterClasses提前进行注册)
    Delphi编写自定义控件以及接口的使用(做了一个TpgDbEdit)
    Log4delphi使用心得
  • 原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6209273.html
Copyright © 2011-2022 走看看