zoukankan      html  css  js  c++  java
  • 多重背包

    【题目描述】

    现有一个容量为M的背包和N种物品,每种物品都有三个属性Vi、Wi、Ci,分别表示这种物品的体积、价值以及件数。

    要求从所给的物品中选出若干件,其体积之和不能超过背包容量,且使所选物品的价值之和最大。

    【输入描述】

    第一行输入两个整数N、M;

    接下来N行,每行输入三个整数Vi、Wi、Ci

    【输出描述】

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

    【样例输入】

    2 8

    2 100 4

    4 100 2

    【样例输出】

    400

    【数据范围及提示】

    对于20%的数据,Ci=1;

    对于60%的数据,N,M <= 500,Ci <= 100;

    对于100%的数据,N,M <= 3000,Ci <= 3000。

    源代码:
    
    #include<cstdio>
    #include<cstring>
    int N,M,f[6001]; //最好开两倍,不明觉厉的数据范围。
    void Solve(int V,int W,int C)
    {
        if (V>M) //特判直接退出。
          return;
        int Head,Tail,Q[6001],F[6001];
        for (int a=0;a<V;a++) //实在装不下该物品的冗余空间。
        {
            Head=1;
            Tail=0;
            Q[++Tail]=a;
            F[a]=f[a]; //初始化。
            for (int b=V+a;b<=M;b+=V) //枚举装下几个该物品的空间。
            {
                while (Head<=Tail&&f[Q[Tail]]-Q[Tail]/V*W<=f[b]-b/V*W) //若此时的冗余空间价值大于队尾的。
                  Tail--;
                Q[++Tail]=b; //Q[]存储的是空间。
                if ((b-Q[Head])/V>C) //若数量超过则去头,因为顺序循环,所以不必使用while()。
                  Head++;
                F[b]=f[Q[Head]]-Q[Head]/V*W+b/V*W; //取最大冗余价值,然后加上应得的物品价值。
            }
            memcpy(f,F,sizeof(F)); //小白鼠数组。
        }
    }
    int main() //多重背包+单调队列优化。
    {
        scanf("%d%d",&N,&M);
        for (int a=1;a<=N;a++)
        {
            int V,W,C;
            scanf("%d%d%d",&V,&W,&C);
            Solve(V,W,C);
        }
        printf("%d",f[M]);
        return 0;
    }
    
    /*
        想一想,为什么这样处理是正确的呢?
        首先会发现,在处理过程中,所有空间情况都只会处理一遍。
        其次,冗余空间的价值不仅包括非物品价值,还包括了比物品更多的价值。
        其实上面都是废话。
        多重背包问题:f[i][j]=max(f[i-1][j-k*V[i]]+k*W[i]) (0 <= k <= C[i]);
        把它变一变,设A=j/V[i]、B=j%V[i],并用k替换(A-k),于是状态转移方程变为:
            f[i][j]=max(f[i-1][B+k*V[i]]-k*W[i])+A*W[i] (A-C[i] <= k <= A)。
    */
  • 相关阅读:
    [ELK] Elasticsearch 安装/配置、启动/停止、加节点/重启
    [ELK] Elastic Stack 的安全性预览
    [Gin] gin.H{} 与 map[string]interface{}
    [Go] 浅谈 Golang struct 与 PHP class 的相似
    [FAQ] Git 修改最后一次的提交人和提交时间 ?
    [Blockchain] 开发完真实的 DApp 后才能得出的结论与看法
    Android 5.0 Phone初始化分析
    推荐一个Android开发懒人库 -- ButterKnife
    ffmpeg 移植到 android 并使用
    为app录制展示gif
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5966275.html
Copyright © 2011-2022 走看看