• luogu P1776 宝物筛选_NOI导刊2010提高(02)


    一道多重背包问题

    多重背包就是

    有n种物品,每种物品有各自的价值和体积,并每种物品有一定数目

    给你一个体积v的背包,求最大价值

    我们可以想到把多重背包分解成01背包来做

    复杂度仍然很高

    那我们想到了某种优化(谁想到的???反正不是我

    每个数都可以用二进制来表示,则每个数都可以拆成2的次方的和

    如 18 = 1 + 2 + 4 + 8 + 3(2 + 1)

    而这几个拆出来的数可以组合成18以内的任何数(不信试试鸭

    这样我们可以把多重背包内的每个物品,拆成1,2,4,8……

    一下子就降低了复杂度对吧

    然后来看看题面

    哇多重背包!

    为什么不多进去几次全都拿出来啊好zz

     emmmm

    那我们看代码实现吧

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define maxn 10000010//不知道拆成几个所以数组开大一点
    
    int f[maxn],v[maxn],w[maxn];
    int cnt;
    
    int main() {
        int n,W,cnt = 0;
        scanf("%d%d",&n,&W);
        for(int i = 1; i <= n; i++) {
            int value,weight,num;
            scanf("%d%d%d",&value,&weight,&num);
            for(int j = 1; j <= num; j <<= 1) {
                v[++cnt] = j * value;
                w[cnt] = j * weight;
                num -= j;//把物品拆开的操作
            }
            if(num) {
                v[++cnt] = value * num;
                w[cnt] = weight * num;
            }
        }
        for(int i = 1; i <= cnt; i++)
            for(int j = W; j >= w[i]; j--) {
                f[j] = max(f[j],f[j - w[i]] + v[i]);//变成01背包~
            }
        printf("%d",f[W]);
        return 0;
    }

    好啦

    这次不是特别水吧www

  • 相关阅读:
    PDF数据提取------2.相关类介绍
    Google搜索的常用技巧
    a helper class for generating xls or csv file
    正则 提取html标签value
    获取 windows地址栏 网页地址栏 文件名
    MSSQL将逗号分隔的字符串转换成列显示
    C# String.Format字符串中包含"{" "}"时需注意的问题
    格式化JSON中时间
    Oracle 10G创建表空间
    Sqlserver取最近一分组中最新一条记录
  • 原文地址:https://www.cnblogs.com/sevenyuanluo/p/10295988.html
Copyright © 2020-2023  润新知