• 多重背包 单调队列优化


    我们注意每个dp【j】可以从dp【j-v】+ w...dp【j-k*v】+k*w转移过来,那个他们的公差是v,我们可以以对v的余数来把他们

    划分成几个小组,比如背包总容量为10,这个物品的体积为3,那么我们可以把0到10划分成{0,3,6,9},{1,4,7,10},{2,5,8},

    我们可以发现不同小组的是不会影响的,因为他们每个的距离都不是3的整数倍。那么对于每个小组的话,我们就可以维护dp【j-k*v】+k*w最大

    ,相当于我们维护一个递减的序列,然后每次要判断合不合法,就是j-c是否大于a【l】,(说明a【l】这个物品的数量不够到达 j //现在先这么理解吧,可能有错)

    然后每次对首都是最大的,

    #include <bits/stdc++.h>
    int a[1005],b[1005],dp[100005];  
    int w,v,c,n,V,l,r;  
    void insert(int x,int y)  
    {  
        while(l<=r&&b[r]<=y)r--;  
        a[++r]=x;b[r]=y;  
    }  
    int main()  
    { 
        int T;
        scanf("%d",&T);
        while(T--)  
        {  
            scanf("%d%d",&V,&n);
            int i,j,d;  
            memset(dp,0,sizeof(dp));      
            for(i=1;i<=n;i++)  
            {  
                scanf("%d%d%d",&v,&w,&c); 
                for(d=0;d<v;d++)  
                {  
                    l=1;  
                    r=0;  
                    for(j=0;j<=(V-d)/v;j++)  
                    {  
                        insert(j,dp[j*v+d]-j*w);  
                        if(a[l]<j-c)l++;  
                        dp[j*v+d]=b[l]+j*w;  
                    }  
                }  
            }  
            printf("%d
    ",dp[V]);  
        }  
        return 0;  
    }  
  • 相关阅读:
    闭包跟装饰器
    几个常见的面试题目
    函数的进阶
    python的生成器和迭代器
    Python的数据类型
    “随手记”开发记录day09
    “随手记”开发记录day08
    “随手记”开发记录day07
    “随手记”开发记录day06
    “随手记”开发记录day05
  • 原文地址:https://www.cnblogs.com/chinacwj/p/8001439.html
Copyright © 2020-2023  润新知