zoukankan      html  css  js  c++  java
  • [HDU1712]ACboy needs your help

    题目大意:ACboy有n门学科,每门学科研究1~m天能获得不同的价值。他总共有m天,求最多能获得多少价值。

    解题思路:典型的分组背包问题。

    这个问题变成了每组物品有若干种策略:是选择本组的某一件,还是一件都不选。也就是说设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(有依赖的背包问题)),由分组的背包问题进一步可定义“泛化物品”的概念,十分有利于解题。

     

    以上摘自《背包九讲》,直接套用即可。

    C++ Code:

    #include<cstdio>
    #include<cstring>
    int a[102][102],n,m,f[102];
    int main(){
    	while(scanf("%d%d",&n,&m)&&n&&m){
    		memset(f,0,sizeof(f));
    		for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j)scanf("%d",&a[i][j]);
    		for(int i=1;i<=n;++i)
    		for(int j=m;j>=0;--j)
    		for(int k=1;k<=j;++k)
    		if(f[j]<f[j-k]+a[i][k])f[j]=f[j-k]+a[i][k];
    		printf("%d
    ",f[m]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    PHP 5.5.0 Alpha5 发布
    Ubuntu Touch 只是另一个 Android 皮肤?
    MariaDB 10 已经为动态列提供文档说明
    Percona Toolkit 2.1.9 发布,MySQL 管理工具
    Oracle Linux 6.4 发布
    Ruby 2.0.0 首个稳定版本(p0)发布
    Apache Pig 0.11.0 发布,大规模数据分析
    Node.js 0.8.21 稳定版发布
    红薯 MySQL 5.5 和 5.6 默认参数值的差异
    Django 1.5 正式版发布,支持 Python 3
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7259963.html
Copyright © 2011-2022 走看看