zoukankan      html  css  js  c++  java
  • 单调队列优化和二进制优化的多重背包模板

    多重背包

    F[i][j]表示对容量为j的背包,处理完前i种物品后,背包内物品可达到的最大总价值。

    num[i]表示第i种物品的数量,cost[i]表示第i种物品的花费,value[i]表示第i种物品的价值。

    mi[i] = min(num[i], j / cost[i])

    放入背包的第i种物品的数目可以是:0、1、2……,可得转移方程:

      F[i][j] = max { F[i - 1] [j – k * cost[i] ] + k * value[i] }  (0 <= k <= mi[i]) 

    上面的式子就是朴素的多重背包转移方程式。

    二进制优化

    二进制优化是基于对于每一种物品的数量分成件数为1,2,4,8……的多个物品

    一种物品可以分为logn件不同的物品

    然后就等同于01背包的问题

    复杂度:O(n*m*logn)

    单调队列优化

    假设 a = j / cost[i],b = j % cost[i],即 j = a * cost[i] + b

    代入朴素的转移方程式,并用k替换a - k得:

    F[i][j] = max { F[i - 1] [b + k * cost[i]] - k * value[i] } + a * value[i]  

    (a – mi[i] <= k <= a) 很重要的判断,用于去除队首的无效值

    单调队列维护队首的max F[i - 1] [b + k * cost[i]] - k * value[i]

    从对位添加F[i - 1] [b + k * cost[i]] - k * value[i]时,若大于队尾,则删除队尾

    复杂度:O(n*m)

    for(int i=1;i<=n;i++)
        {
            for(int j=0;j<cost[i];j++)
            {
                q[head=tail=1]=make_pair(f[j],0);
                for(int k=j+cost[i];k<=m;k+=cost[i])
                {
                    int a=k/cost[i],t=f[k]-a*value[i];
                    while(head<=tail&&q[tail].first<=t)tail--;
                    q[++tail]=make_pair(t,a);
                    while(head<=tail&&q[head].second+num[i]<a)head++;
                    f[k]=max(f[k],q[head].first+a*value[i]);
                }
            }
        }
    View Code

     

  • 相关阅读:
    题解:luoguP1861 星之器
    题解:LOJ540游戏
    Yii框架常见问题
    常用ubuntu命令
    Python中的映射数据类型 dict
    Python中的编码问题:ASCII码 Unicoden编码 UTF8编码
    Python中的列表、元组的增、删、改、查
    Python 数据类型之 集合 set
    Python中常见的字符串的操作方法:
    Python程序的控制结构用多分支结构处理身体指标BMI问题
  • 原文地址:https://www.cnblogs.com/solvit/p/9530633.html
Copyright © 2011-2022 走看看