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

Mid-Central European Regional Contest 1999

题目大意:

  有很多很多的物品,但是总数不过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:\nCan‘t be divided.\n\n",now);
            continue;
        }
        sum_value/=2;
        if(Check_Answer()) printf("Collection #%d:\nCan be divided.\n\n",now);
        else printf("Collection #%d:\nCan‘t be divided.\n\n",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:\nCan‘t be divided.\n\n",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:\nCan be divided.\n\n",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:\nCan‘t be divided.\n\n",now);
    }
    return 0;
}

时间: 2024-08-14 18:51:21

AC日记——Dividing poj 1014的相关文章

AC日记——Crane poj 2991

POJ - 2991 思路: 向量旋转: 代码: #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 400005 const double pi=acos(-1.0); struct TreeNodeType { int l,r,R,mid,

AC日记——Oulipo poj 3461

Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 37958   Accepted: 15282 Description The French author Georges Perec (1936–1982) once wrote a book, La disparition, without the letter 'e'. He was a member of the Oulipo group. A quote from

AC日记——Dining poj 3281

[POJ-3281] 思路: 把牛拆点: s向食物连边,流量1: 饮料向t连边,流量1: 食物向牛1连边,流量1: 牛2向饮料连边,流量1: 最大流: 来,上代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 2005 #define INF 0x7fffffff int n,f,

POJ 1014 Dividing 背包

这道题使用多重背包,不过其实我也不太明白为什么叫这个名字. 因为感觉不是什么多重,而是物体的分解问题. 就是比如一个物体有数量限制,比如是13,那么就需要把这个物体分解为1, 2, 4, 6 如果这个物体有数量为25,那么就分解为1, 2, 4, 8, 10 看出规律吗,就是分成2的倍数加上位数,比如6 = 13 - 1 - 2 - 4, 10 = 25 - 1 - 2 - 4 - 8,呵呵,为什么这么分解? 因为这样分解之后就可以组合成所有1到13的数,为25的时候可以组合成所有1到25的数啦

POJ 1014 Dividing (多重背包)

Dividing Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 58921   Accepted: 15200 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 marbl

证明 poj 1014 取模优化剪枝,部分递归 存在错误

做了这道题目,我才发现一道题即便可行,但是正确性也不一定.多数由于题目数据太弱. poj 1014 Dividing 题目大意:有6堆石头,权重分别为1 2 3 4 5 6,要求输入 每堆个数 ,求是否可以平分石头使得两堆价值相同. 网上对这道题的做法就两种,其中有错误的版本,却也可以AC.起初这让我等菜鸟感慨代码的简洁,但无法得出正确性的证明 接下来就对两种方法的错误性进行证明. 1.多重背包 #include <map> #include<string> #include &l

证明 poj 1014 模优化修剪,部分递归 有错误

这个问题是存在做.我发现即使是可行的一个问题,但不一定正确. 大部分数据疲软,因为主题. id=1014">poj 1014 Dividing 题目大意:有6堆石头,权重分别为1 2 3 4 5 6,要求输入 每堆个数 ,求能否够平分石头使得两堆价值同样. 网上对这道题的做法就两种,当中有错误的版本号.却也能够AC. 起初这让我等菜鸟感慨代码的简洁,但无法得出正确性的证明 接下来就对两种方法的错误性进行证明. 1.多重背包 #include <map> #include<

AC日记——Aragorn&#39;s Story HDU 3966

Aragorn's Story Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 10510    Accepted Submission(s): 2766 Problem Description Our protagonist is the handsome human prince Aragorn comes from The Lor

POJ 1014: Dividing

写在前面: 本题非常有意思, 因此我在编程前后和撰写本文前, 在网上查询并阅读了大量关于本题的解题报告. 当中有两种似是而非但提交后却可以 AC 的解法引起了我的兴趣, 一是原作者宣称的 "DFS 解", 二是原作者宣称的 "扩展的找零问题解". 我对这两种解法的源码进行了细致的分析, 找到了它们的问题之所在. 以下我会先对这两种错误解法进行分析和讨论, 然后再给出正确的思路. 错误解法 1: 依照价值从大到小的顺序尝试凑数 (不回溯). 因为裁判的測试数据不够全面