• 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");    
    
        }
  • 相关阅读:
    算法学习记录-排序——快速排序
    算法学习记录-排序——归并排序
    算法学习记录-排序——堆排序
    算法学习记录-排序——希尔排序
    算法学习记录-排序——插入排序(Insertion Sort)
    Windows 10 安装 Vim
    Flash Basics
    NVMe
    vim usage tips
    Mac OS Terminal Commands 02
  • 原文地址:https://www.cnblogs.com/chengxuyuancc/p/2958247.html
Copyright © 2020-2023  润新知