zoukankan      html  css  js  c++  java
  • ZOJ 3164 Cookie Choice(终极背包)

    题意:

    给出N类物品,有价值,数量,价格

    还有一些限制组,限制的组里面最多只能选一类物品,问D钱最多能获得的价值,并且D钱必须花完

    思路:

    看完背包9讲,感觉这一题还是不难理解的。首先,对于没有组的限制的X类物品,进行一遍背包(01背包、完全背包、多重背包)。

    其次,对于有组的限制的物品,就需要再次考虑下了。这次要用到泛化背包和分组背包的思想。每一组只能选择组里面的一类物品。

    于是试图考虑,如果我分给这个组V(range from 0 to D)的容量,能够最多拿到多少价值。因为这个组有X类物品,只能选择一类,

    所以需要先对这个组的每一类物品进行一次01背包,获得分配给这类物品V的容量取得的最大价值,然后再对这个组的X类物品进行分组背包。

    最后,针对上述组进行一次分组背包,问题得以解决。

    (第一次开始自己尝试描述算法思路,Orz Orz,坚持坚持)

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    #define max(a,b) (((a) > (b)) ? (a) : (b))
    
    const int MAXN = 1500;
    const int INF = 1e9;
    int Ki[MAXN], Ei[MAXN], Pi[MAXN];
    int w[10][MAXN], f[MAXN];
    int n, d, g;
    
    void init_input()
    {
        for (int i = 1; i <= n; ++i)
            scanf("%d %d %d", &Ki[i], &Ei[i], &Pi[i]);
    
        scanf("%d%*c", &g);
        memset(f, 0, sizeof(f));
        char s[1000];
        for (int i = 1; i <= g; ++i)
        {
            gets(s);
            int j = 0;
            while (j < strlen(s))
            {
                if ('1' <= s[j] && s[j] <= '9')
                {
                    int sum = 0;
                    while ('0' <= s[j] && s[j] <= '9')
                        sum = 10 * sum + s[j] - '0', ++j;
                    f[sum] = i;
                } 
                else 
                    ++j;
            }
        }
    }
    
    void init_dp(int dp[])
    {
        fill(dp, dp + d + 1, -INF);
        dp[0] = 0;
    }
    
    void complete_pack(int w, int v, int dp[])
    {
        for (int i = w; i <= d; ++i)
            if (dp[i-w] > -INF)             // 必须装满的时候,是需要这么一个判断的。-INF表示没有合法解
                dp[i] = max(dp[i], dp[i-w] + v);
    }
    
    void zero_one_pack(int w, int v, int dp[])
    {
        for (int i = d; i >= w; --i)
            if (dp[i-w] > -INF)
                dp[i] = max(dp[i], dp[i-w] + v);
    }
    
    void multiple_pack(int w, int v, int n, int dp[])
    {
        int i = 1, c = n;
    
        while (i < c)
        {
            zero_one_pack(i * w, i * v, dp);
            c -= i;
            i *= 2;
        }
        if (c)
            zero_one_pack(c * w, c * v, dp);
    }
    
    int main()
    {
        while (scanf("%d %d", &n, &d) != EOF)
        {
            init_input();
    
            int dp[MAXN], temp[MAXN];
    
            init_dp(dp);
            for (int i = 1; i <= g; ++i)
                init_dp(w[i]);
    
            for (int i = 1; i <= n; ++i)
            {
                if (f[i])
                    init_dp(temp);
    
                if (!Ki[i] || Ki[i] * Pi[i] >= d)
                    complete_pack(Pi[i], Ei[i], f[i] ? temp : dp);
                else
                    multiple_pack(Pi[i], Ei[i], Ki[i], f[i] ? temp : dp);
    
                if (f[i])   
                    for (int j = 0; j <= d; ++j)
                        w[f[i]][j] = max(w[f[i]][j], temp[j]);
            }
            for (int i = 1; i <= g; ++i)    // w[g][d] : g个组,每个组有d个物品,每个组最多选择其中一个
                for (int j = d; j >= 0; --j)
                    for (int k = 0; k <= j; ++k)
                        if (w[i][k] > -INF && dp[j-k] > -INF)
                            dp[j] = max(dp[j], dp[j-k] + w[i][k]);
    
            if (dp[d] >= 0)
                printf("%d\n", dp[d]);
            else 
                printf("i'm sorry...\n");
        }
        return 0;
    }

     

    -------------------------------------------------------

    kedebug

    Department of Computer Science and Engineering,

    Shanghai Jiao Tong University

    E-mail: kedebug0@gmail.com

    GitHub: http://github.com/kedebug

    -------------------------------------------------------

  • 相关阅读:
    数据处理
    Interleaving String
    Distinct Subsequences
    caffe 输入图像图像加高斯噪声
    caffe resize用interpolation
    软件測试基本方法(七)之验收測试
    CSS入门学习
    bzoj1458 士兵占据
    Swift高阶函数介绍(闭包、Map、Filter、Reduce)
    每天一点儿Java--list
  • 原文地址:https://www.cnblogs.com/kedebug/p/2760744.html
Copyright © 2011-2022 走看看