• hdu_1059_多重背包


    题目的意思:

    有一堆大理石,按其大小分为1-6种价值,两个人想分得的价值相同的大理石,已知每种价值的大理石个数,问是否能让两个人分得价值相同的大理石?

    题目输入:

    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.

     

    解题思路:

    很明显这是一个多重背包问题,可以将问题转化为0/1背包问题解决。将每种价值v的大理石数x,按二进制分解成价值为1*v,2*v,4*v…,2^k-1*v,(x-2^k+1)*v的大理石,其它价值的大理石也这样分解,这样就转化成为0/1背包问题了(由于1,2,4…,2^k-1,x-2^k+1可以组成0~x中的任意数值)。后面的问题就简单了,只要能找到一种取分解后大理石的取法,使取得后的大理石的总价值等于全部大理石总价值的一半就说明可以平均分配,否则就不能。

     

    代码:

    #include <stdio.h>
    
    #include <string.h>
    
     
    
    int ans[120001];
    
    int half; 
    
    int data[7];
    
    int tpe[20];
    
     
    
    int main(void)
    
    {
    
        int count = 1;
    
       int i,j,k;
    
    int cur_max;
    
     
    
    tpe[0] = 1;
    
    for (i = 1; i < 20; i ++)
    
       tpe[i] = 2 * tpe[i - 1];
    
     
    
        while (1)
    
        {
    
            scanf("%d%d%d%d%d%d", data + 1, data + 2, data + 3, data + 4, data + 5, data + 6);    
    
            if (!data[1] && !data[2] && !data[3] && !data[4] && !data[5] && !data[6])
    
                break;
    
            fprintf(stdout, "Collection #%d:\n", count ++);
    
    half = data[1] + data[2] * 2 + data[3] * 3 + data[4] * 4 + data[5] * 5 + data[6] * 6;
    
            if (half % 2 != 0)
    
            {
    
                fprintf(stdout, "Can't be divided.\n\n");    
    
                continue;
    
            }
    
    half /= 2;
    
            memset(ans, 0, (half + 1) * sizeof(int));
    
            for (i = 0; i <= data[1]; i ++)
    
                ans[i] = 1;
    
            cur_max = data[1];
    
            for (i = 2; i < 7; i ++)
    
            {
    
       if (ans[half])
    
      break;
    
       data[i] = data[i] * i > half ? half / i : data[i];
    
                cur_max += data[i] * i;    
    
                if (cur_max > half)
    
                    cur_max = half;
    
        k = 0;
    
    while (tpe[k + 1] - 1 <= data[i])
    
    {
    
                 for (j = cur_max; j > data[1] && j - tpe[k] * i>= 0; j --)
    
       if (!ans[j])
    
        ans[j] = ans[j - tpe[k] * i];
    
    k ++;
    
    }
    
    for (j = cur_max; j > data[1] && j - (data[i] - tpe[k] + 1) * i >= 0; j --)
    
       if (!ans[j])//特别注意要判断是否为1,开始调了好久,就因为这个没判断啊!
    
    ans[j] = ans[j - (data[i] - tpe[k] + 1) * i];
    
            }    
    
            if (ans[half])
    
                fprintf(stdout, "Can be divided.\n\n");
    
            else
    
                fprintf(stdout, "Can't be divided.\n\n");    
    
        }
  • 相关阅读:
    找出水王
    第九周进度表
    [设计模式]组合模式
    [设计模式]外观模式
    [设计模式]策略模式
    [设计模式] 6个设计遵循基本原则
    [OSGI]Eclipse4.2 OSGI依赖Bundle
    [xfire]使用xfire开发webservice的简单示例
    [HTML5 Canvas学习]使用颜色和透明度
    [HTML5 Canvas学习]绘制矩形
  • 原文地址:https://www.cnblogs.com/chengxuyuancc/p/2958247.html
Copyright © 2020-2023  润新知