• hdu(1059) Dividing(多重背包)


    题意:输入六个数,价值分别为1——6,输入的数代表该价值的物品的个数;求能否平均分。

    key:如果奇数肯定不能分,直接输出答案。偶数的话,就是多重背包问题。 试过两种做法,第一种是背包九讲的二进制优化,写三个函数,分别是bag01, bagall, bagmulti~第二种是直接多重背包~

    #include <iostream>
    #include <algorithm>
    #include <string.h>
    #include <stdio.h>
    const int maxn = 120000 + 6;   //20000 * 6
    int dp[maxn];
    int val[8];  //输入的六组数
    int sum, sumh;
    
    using namespace std;
    
    void bag01(int w, int v)          //01背包
    {
        for(int i = sumh; i >= w; i--)
            if(dp[i] < dp[i - w] + v)
                dp[i] = dp[i - w] + v;
    }
    
    void allbag(int w, int v)   //完全背包
    {
        for(int i = w; i <= sumh; i++)
            if(dp[i] < dp[i - w] + v)
                dp[i] = dp[i - w] + v;
    }
    
    void multibag(int w, int v, int n)   //多重背包,“背包九讲”有模版
    {
        if(w * n >= sumh)           //假如重量 * 数量,大于背包,就变成完全背包的情况,即该物品可任意取
            allbag(w, v);
        else{                           //进行二进制优化
            int k = 1;
            while(k < n){
                bag01(k * w, k * v);
                n = n - k;
                k = 2 * k;
            }
                bag01(w * n, v * n);
        }
    }
    
    
    int main()
    {
        int t = 1;
        while(scanf("%d%d%d%d%d%d", &val[1], &val[2], &val[3], &val[4], &val[5], &val[6]) != EOF){
            memset(dp, 0, sizeof(dp));
            sum = val[1] + val[2] * 2 + val[3] * 3 + val[4] * 4 + val[5] * 5 + val[6] * 6;
            if(sum == 0)
                break;
            sumh = sum / 2;
            if(sum % 2 != 0){          //奇数的话可直接输出不能
                printf("Collection #%d:
    ", t);
                printf("Can't be divided.
    
    ");
                t++;
                continue;
            }
            else{
                for(int i = 1; i <= 6; i++){            //多重背包
                    multibag(i, i, val[i]);
                }
                if(dp[sumh] == sumh){
                    printf("Collection #%d:
    ", t);
                    printf("Can be divided.
    
    ");
                    t++;
                }
                else{
                    printf("Collection #%d:
    ", t);
                    printf("Can't be divided.
    
    ");
                    t++;
                }
            }
        }
        return 0;
    }

    这是第二种做法!

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    
    const int maxn = 120000 + 6;   //20000 * 6
    int dp[maxn];
    int val[8];  //输入的六组数
    int sum, sumh;
    
    using namespace std;
    
    int main()
    {
        int t = 1;
        while(scanf("%d%d%d%d%d%d", &val[1], &val[2], &val[3], &val[4], &val[5], &val[6]) != EOF){
            memset(dp, 0, sizeof(dp));
            sum = val[1] + val[2] * 2 + val[3] * 3 + val[4] * 4 + val[5] * 5 + val[6] * 6;
            if(sum == 0)
                break;
            sumh = sum / 2;
            if(sum % 2 != 0){          //奇数的话可直接输出不能
                printf("Collection #%d:
    ", t);
                printf("Can't be divided.
    
    ");
                t++;
                continue;
            }
            else{
                for(int i = 1; i <= 6; i++){  //多重背包
                    int cnt[maxn];             //用来表示第J个背包里含有的I物品的数量 
                    memset(cnt, 0, sizeof(cnt));
                   for(int j = i;j <= sumh; j++){
                        if(cnt[j - i] + 1 <= val[i] && i + dp[j - i] > dp[j]){
                            dp[j] = i + dp[j - i];
                            cnt[j] = cnt[j - i] + 1;
                        }
                   }
                }
                if(dp[sumh] == sumh){
                    printf("Collection #%d:
    ", t);
                    printf("Can be divided.
    
    ");
                    t++;
                }
                else{
                    printf("Collection #%d:
    ", t);
                    printf("Can't be divided.
    
    ");
                    t++;
                }
            }
        }
        return 0;
    }
     
  • 相关阅读:
    用小百合学python
    驱动对象 设备对象 设备栈 乱杂谈
    [转]很经典的http协议详解
    利用VMWare和WinDbg调试驱动程序
    GCC基础
    史上最著名的10个思想实验 (转)
    windows XP下驱动开发环境设置(DDK+VC6.0)
    守护进程
    驱动SYS开发总结
    ASP.NET学习笔记1
  • 原文地址:https://www.cnblogs.com/Joe962850924/p/4276088.html
Copyright © 2020-2023  润新知