POJ 1014 Dividing 【DP 之 多重背包 / 二进制优化】


Language:
Default

Dividing

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 63647   Accepted: 16488

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.

题意:略..O(∩_∩)O哈哈~偷回懒~~~~

这是一道比较裸的多重背包可以直接套用多重背包的模板,但是这个题目只需要判断可行性,我们只需要二进制处理一下即可,背包有很多变式,我们不能每次都是套用模板,更要学会各种背包的问题的思路。比如多重背包,最核心的思想就是二进制优化了,用二进制优化,可以将复杂度O(VΣMi)降低到O(VΣlogMi),真是神奇!!!

那么,什么是多重背包?多重背包:有N种物品和一个容量为V的背包。第i种物品最多有Mi件可用,每件耗费的空间是Ci,价值是Wi。求解将哪O(VΣlogMi)些物品装入背包可使这些物品的耗费的空间总和不超过背包容量,且价值总和最大。

这里还使用到了滚动数组来优化空间复杂度。

最后,给大家提供两种结题

//方法一:Memory :252KB Time:16ms
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 LL;
const int maxn = 20000 + 5;
int num[7], sum;
bool suc, dp[6 * maxn];
void pack01(int C)
{
    for(int v = sum; v >= C; v--)
        dp[v] |= dp[v - C];
}
int main()
{
    int cas = 0;
    //freopen("input.in", "r", stdin);
    while(~scanf("%d", &num[1]))
    {
        sum = num[1];
        for(int i = 2; i <= 6; i++)
        {
            scanf("%d", &num[i]);
            sum += num[i] * i;
        }
        if(sum == 0) break;
        if(cas) puts("");
        printf("Collection #%d:\n", ++cas);
        if(sum & 1)
        {
            printf("Can't be divided.\n");
            continue;
        }
        suc = false;
        sum >>= 1;
        memset(dp, false, sizeof(dp));
        dp[0] = true;
        for(int i = 1; i <= 6; i++)
        {
            int k = 1;
            while(k < num[i])
            {
                pack01(k * i);
                num[i] -= k;
                k <<= 1;
            }
            pack01(num[i]*i);
        }
        printf("%s\n", dp[sum] ? "Can be divided." : "Can't be divided.");
    }
    return 0;
}
<pre name="code" class="cpp">//方法二:多重背包模板 Memory:620KB Time:16ms
#include <queue>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 LL;
const int maxn = 20000+5;
int num[7],dp[maxn*6],V;
bool suc;
void Pack01(int C,int W)
{
    if(suc) return ;
    for(int v = V;v >= C;v--)
    {
        dp[v] = max(dp[v],dp[v-C]+W);
        if(dp[v] == V)
        {
            suc = true;
            return;
        }
    }
}
void ComplePack(int C,int W)
{
    if(suc) return;
    for(int v = C;v <= V;v++)
    {
        dp[v] = max(dp[v],dp[v-C]+W);
        if(dp[v] == V)
        {
            suc = true;
            return;
        }
    }
}
void MultiPack(int C,int W,int M)
{
    if(C*M>=V)
    {
        ComplePack(C,W);
        return;
    }
    int k = 1;
    while(k < M)
    {
        Pack01(k*C,k*W);
        if(suc) return;
        M -= k;
        k <<= 1;
    }
    Pack01(C*M,W*M);
}
int main()
{
    int cas = 0;
    //freopen("input.in","r",stdin);
    while(~scanf("%d",&num[1]))
    {
        int sum = num[1];
        for(int i = 2; i <= 6; i++)
        {
            scanf("%d",&num[i]);
            sum += num[i]*i;
        }
        if(sum == 0) break;
        if(cas) puts("");
        printf("Collection #%d:\n",++cas);
        if(sum & 1)
        {
            printf("Can't be divided.\n");
            continue;
        }
        suc = false;
        V = sum>>1;
        memset(dp,-1,sizeof(dp));
        dp[0] = 0;
        for (int i = 1;i <= 6;i++)
        {
            MultiPack(i,i,num[i]);
            if(suc) break;
        }
        printf("%s\n",suc?"Can be divided.":"Can't be divided.");
    }
    return 0;
}

</pre><pre>



版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2025-01-17 21:55:32

POJ 1014 Dividing 【DP 之 多重背包 / 二进制优化】的相关文章

[多重背包+二进制优化]HDU1059 Dividing

题目链接 题目大意: 两个人要把一堆宝珠,在不能切割的情况下按照价值平分,他们把宝珠分成6种价值,每种价值的宝珠n个. n<=200000 思考: 首先如果加和下来的价值是一个偶数 那么还分毛啊,直接gg. 之后多重背包二进制优化 转换为 01背包. 我们可以把价值 同时当做宝珠的空间和价值. 那么我们现在要求的是 在 空间为一半的情况下,能否找到价值为 一半的情况. 1 #include <cstdio> 2 #include <algorithm> 3 #include

hdu1059 dp(多重背包二进制优化)

hdu1059 题意,现在有价值为1.2.3.4.5.6的石头若干块,块数已知,问能否将这些石头分成两堆,且两堆价值相等. 很显然,愚蠢的我一开始并想不到什么多重背包二进制优化```因为我连听都没有听过```不得不吐槽自己的知识面太窄```于是,我用了母函数写这题,母函数的做法并没有问题,但是由于这道题的数据很大,母函数轻轻松松就超时了,于是,我又很努力地在母函数循环的优化上面想出路,改改改,各种改之后依旧TLE,01背包的做法显然也是会超时的,DISCUSS里的母函数做法优化方式都是模上一个大

HDU 1059 多重背包+二进制优化

Dividing Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 16909    Accepted Submission(s): 4729 Problem Description Marsha and Bill own a collection of marbles. They want to split the collection

台州 OJ 2537 Charlie&#39;s Change 多重背包 二进制优化 路径记录

描述 Charlie is a driver of Advanced Cargo Movement, Ltd. Charlie drives a lot and so he often buys coffee at coffee vending machines at motorests. Charlie hates change. That is basically the setup of your next task. Your program will be given numbers

14年省赛---多重部分和问题(多重背包+二进制优化)

1210: F.多重部分和问题 时间限制: 1 Sec  内存限制: 64 MB提交: 18  解决: 14 题目描述 有n种不同大小的数字,每种各个.判断是否可以从这些数字之中选出若干使它们的和恰好为K. 输入 首先是一个正整数T(1<=T<=100)接下来是T组数据 每组数据第一行是一个正整数n(1<=n<=100),表示有n种不同大小的数字 第二行是n个不同大小的正整数ai(1<=ai<=100000)第三行是n个正整数mi(1<=mi<=100000

POJ 1014 Dividing(多重背包+二进制优化)

http://poj.org/problem?id=1014 题意:6个物品,每个物品都有其价值和数量,判断是否能价值平分. 思路: 多重背包.利用二进制来转化成0-1背包求解. 1 #include<iostream> 2 #include<string> 3 #include<cstring> 4 #include<cstdio> 5 #include<algorithm> 6 using namespace std; 7 8 const i

POJ 1014 Dividing【多重背包+二进制优化】

大意: 价值1, 2, 3, ……, 6的物品分别a1, a2, ……, a5, a6件 问能否把这些物品分成两份,使其具有相同的价值(所有物品必须全部用上) 分析: 给个物品有多件,即多重背包 只要看能不能将这些物品拼成   总价值 的 一半就可以了 转化为01背包是用二进制优化,否则会超时 代码: 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std;

POJ 1276 Cash Machine 多重背包--二进制优化

点击打开链接 Cash Machine Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 28337   Accepted: 10113 Description A Bank plans to install a machine for cash withdrawal. The machine is able to deliver appropriate @ bills for a requested cash amount

Cash Machine POJ - 1276 多重背包二进制优化

题意:多重背包模型  n种物品 每个m个  问背包容量下最多拿多少 这里要用二进制优化不然会超时 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int maxn=100000+10; 6 int dp[maxn]; 7 int w[500],c[50]; 8 int main(){ 9 10 int n,m,maxnum; 11 whi