• 多重背包(二进制优化)


    链接:https://www.acwing.com/problem/content/5/

    N种物品和一个容量是 V 的背包。

    i 种物品最多有 si 件,每件体积是 vi,价值是 wi

    求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
    输出最大价值。

    输入格式

    第一行两个整数,NV,用空格隔开,分别表示物品种数和背包容积。

    接下来有 N 行,每行三个整数 vi,wi,si,用空格隔开,分别表示第 i 种物品的体积、价值和数量。

    输出格式

    输出一个整数,表示最大价值。

    数据范围

    0<N1000
    0<V2000
    0<vi,wi,si2000

    提示:

    本题考查多重背包的二进制优化方法。

    输入样例

    4 5
    1 2 3
    2 4 1
    3 4 3
    4 5 2
    

    输出样例:

    10


    解题思路:把多重背包变成01背包
    二进制优化:如果说把其物品都分成一分的话,会超时,
    所以其子问题就是:一个数n,最少要多少个数才能把从1-n中的所有数表示出来;
    答案是:log2(n)上取整个数
    如:7的 1 2 4(2^0 2^1 2^2)
    上面7是个特殊的例子:
    再如10:如果用 1 2 4 8 表示的话会超过10
    所以用1 2 4 3(10-1-2-4)
    AC代码:
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 20110;
    int v[N],w[N],s[N];
    int dp[N];
    int main()
    {
        int n,m,v1,w1,s,cut=0;
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            cin>>v1>>w1>>s;
            int k=1;
            while(k<=s){
                cut++;
                v[cut]=v1*k;
                w[cut]=w1*k;
                s-=k;
                k*=2;
            }
            if(s>0){
                cut++;
                v[cut]=v1*s;
                w[cut]=w1*s;
            }
        }
        n=cut;
        for(int i=1;i<=n;i++){
            for(int j=m;j>=v[i];j--){
                dp[j]=max(dp[j],dp[j-v[i]]+w[i]); 
            }
        }
        printf("%d",dp[m]);    
    } 
    View Code
     
  • 相关阅读:
    axis2 WebService的发布与调用
    sql语句having子句用法,很多时候你曾忘掉
    linux下tomcat开机自启动
    框架使用的技术主要是SpringMVC 在此基础上进行扩展
    SpringMVC整合Mongodb开发 架构搭建
    解决Linux下3T硬盘分区只有2T(2199G)可用
    ubuntu cp(copy) command
    Linux如何根据UUID自动挂载磁盘分区
    python exec和eval
    在OpenERP报表中使用selection 类型字段
  • 原文地址:https://www.cnblogs.com/lipu123/p/12149851.html
Copyright © 2020-2023  润新知