zoukankan      html  css  js  c++  java
  • 杭电1712 分组背包

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1712

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <cstdlib>
     6 #include <cmath>
     7 #include <set>
     8 #include <map>
     9 #include <vector>
    10 using namespace std;
    11 
    12 int max(int a, int b)
    13 {
    14     return a > b ? a : b;
    15 }
    16 int main()
    17 {
    18     int n, m, i, j, k, a[110][110], dp[110];
    19     while(~scanf("%d %d", &n, &m))
    20     {
    21         if(n == 0 && m == 0)
    22             break;
    23         for(i = 1; i <= n; i++)
    24             for(j = 1; j <= m; j++)
    25                 scanf("%d", &a[i][j]);
    26         memset(dp, 0, sizeof(dp));
    27         for(i = 1; i <= n; i++)
    28         {
    29             for(j = m; j > 0; j--)//一定要从大到小
    30             {
    31                 for(k = 0; k < j; k++)
    32                     dp[j] = max(dp[j], dp[k] + a[i][j - k]);
    33             }
    34         }
    35         printf("%d
    ", dp[m]);
    36     }
    37     return 0;
    38 }

    问题

    有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

    算法

    这个问题变成了每组物品有若干种策略:是选择本组的某一件,还是一件都不选。也就是说设f[k][v]表示前k组物品花费费用v能取得的最大权值,则有:

    f[k][v]=max{f[k-1][v],f[k-1][v-c[i]]+w[i]|物品i属于组k}

    使用一维数组的伪代码如下:

    for 所有的组k
        for v=V..0
            for 所有的i属于组k
                f[v]=max{f[v],f[v-c[i]]+w[i]}
    

    注意这里的三层循环的顺序,甚至在本文的第一个beta版中我自己都写错了。“for v=V..0”这一层循环必须在“for 所有的i属于组k”之外。这样才能保证每一组内的物品最多只有一个会被添加到背包中。

    另外,显然可以对每组内的物品应用P02中“一个简单有效的优化”。

  • 相关阅读:
    HDU 1058 Humble Numbers
    HDU 1421 搬寝室
    HDU 1176 免费馅饼
    七种排序算法的实现和总结
    算法纲要
    UVa401 回文词
    UVa 10361 Automatic Poetry
    UVa 537 Artificial Intelligence?
    UVa 409 Excuses, Excuses!
    UVa 10878 Decode the tape
  • 原文地址:https://www.cnblogs.com/luomi/p/5467416.html
Copyright © 2011-2022 走看看