码迷,mamicode.com
首页 > 其他好文 > 详细

多重背包单调队列优化

时间:2017-09-08 10:16:46      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:01背包   更新   log   完全   head   int   技术分享   单调队列   大于   

技术分享
for (int i = 1; i <= n; ++i) {
    Ni = Num[i]; Vi = V[i]; Wi = W[i];
    for (int j = 0; j < Vi; ++j) {
        Head1 = Tail1 = 0;
        Head2 = Tail2 = 0;
        Cnt = 0;
        for (int k = j; k <= m; k += Vi) {
            if (Tail1 - Head1 == Ni + 1) {
                if (Q2[Head2 + 1] == Q1[Head1 + 1]) ++Head2;
                ++Head1;
            }
            t = f[k] - Cnt * Wi;
            Q1[++Tail1] = t;
            while (Head2 < Tail2 && Q2[Tail2] < t) --Tail2;
            Q2[++Tail2] = t;
            f[k] = Q2[Head2 + 1] + Cnt * Wi; 
            ++Cnt;
        }
    }
}
View Code

 

考虑多重背包与01背包,完全背包的区别。

多重背包每种物品只能选最多m个。

那么我们的任务就是,如何控制多重背包最多选m个物品。

自然想到滑动窗口。当窗口宽度大于v[i]*m的时候把前面的元素删除

但是如果单纯的滑动,对与某一个f[k],f[k-v[i]]可能已经被这个物品更新过了

设V=a*vi+b;

设k=c*vi+d;

枚举c,d就可以均匀的枚举到所有小于V的值,且不重复,复杂度O(V)

于是枚举每一个d值,对于每个d再枚举c,当c>m时将队首删除

每一个枚举到的值用单调队列维护。每次f[k]就是队列最大值

 

多重背包单调队列优化

标签:01背包   更新   log   完全   head   int   技术分享   单调队列   大于   

原文地址:http://www.cnblogs.com/Amphetamine/p/7492791.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!