zoukankan      html  css  js  c++  java
  • HDU 1712 分组背包问题

    http://acm.hdu.edu.cn/showproblem.php?pid=1712

    物品分多组,每组中的每件都是冲突的,那么,背包问题变成,在某组中取一个,使得价值达到最大,或者这组一个都不取能使价值达到最大,在01背包基础上加一个循环就可以,在减去体积的时候依次减去每组每一个的体积,这里的体积正好对应纵坐标,所以不必再抽象成c[i]了,价值w[i]<-a[i][j];

    问题
    有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中“一个简单有效的优化”。
    小结
    分组的背包问题将彼此互斥的若干物品称为一个组,这建立了一个很好的模型。不少背包问题的变形都可以转化为分组的背包问题(例如P07),由分组的背包问题进一步可定义“泛化物品”的概念,十分有利于解题。

     1 #include<stdio.h>
     2 int max(int a,int b)
     3 {
     4     return a>b?a:b;
     5 }
     6 int main()
     7 {
     8     int i,k,j,n,m,dp[110],a[110][110];
     9     while(scanf("%d%d",&n,&m),n||m)
    10     {
    11        for(i=1;i<=n;i++)
    12         for(j=1;j<=m;j++)
    13           scanf("%d",&a[i][j]);
    14        dp[0]=0;
    15        for(i=1;i<110;i++)dp[i]=0;
    16        for(k=1;k<=n;k++)
    17         for(j=m;j>=0;j--)
    18           for(i=0;i<=j;i++)
    19         dp[j]=max(dp[j],dp[j-i]+a[k][i]);//这里体积正好对应纵坐标,所以k组中的i就是相对应物品中的体积,价值是a[k][i] 
    20        printf("%d
    ",dp[m]);
    21     }
    22     return 0;
    23 }
    View Code
  • 相关阅读:
    图灵测试
    百度面试题
    【javascript每日一练】- 插入排序
    各种排序讲解
    【javascript每日一练】- 多维数组
    不用JQuery,原生Javascript实现Ajax功能及相关知识点
    【javascript每日一练】- 无序数组排序
    前端面试题
    前端重构面试题
    面试题
  • 原文地址:https://www.cnblogs.com/huzhenbo113/p/3248681.html
Copyright © 2011-2022 走看看