• 单调队列优化和二进制优化的多重背包模板


    多重背包

    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

     

  • 相关阅读:
    POJ 2427 Smith's Problem Pell方程
    Codeforces Round #194 (Div. 2) 部分题解
    SPOJ 3899. Finding Fractions 连分数
    Codeforces Round #193 (Div. 2) 部分题解
    HDU 1402 A * B Problem Plus FFT
    F的ACM暑期集训计划
    HDU 4607 Park Visit HDU暑期多校1
    Windows 下 Sublime Text 默认打开方式问题解决办法
    Roman To Integer
    Longest Common Prefix
  • 原文地址:https://www.cnblogs.com/solvit/p/9530633.html
Copyright © 2020-2023  润新知