Multiple poj1014 backpack - Monotone queue Optimization

Multiple backpack, we all know when the complexity of O (n ^ 3) of. But this complexity when many do not have access in the title. So there will be a variety of optimization, such as: binary grouping, stack optimization and so on.
But the best thing is monotonous queue optimization.

When it is how to achieve it?
Or in the diving pod1014 for it!
In this question can be solved by using multiple backpack.

First, both ends monotone queue deleted, inserted at the end of the queue, which satisfies the monotonicity internal queue.
We control the queue length and its monotony.
Here we use the w, v, sum to represent the weight, value, quantity.
First, to classify the remaining Class I f [x] mod w of.
A weight w in the article, only the f [xw], f [x -2 * w], f [x-3 * w] ... f [xk * w] answers affected.
But different f [xk * w] as the plus k * v is different.
At this time, there is a smart way to solve this problem.
Setting x = k * x + c,
then the queue when it into monotone subtracting k * v,
if y = m * x + c, it is necessary to remove the maximum queue monotonous plus m * v.
When then removed f [x], f [x ] = f [x] + (ca) * v.
This value, plus the value that is exactly needed.

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define For(aa,bb,cc) for(int aa=bb;aa<=cc;++aa)
#define Set(aa,bb) memset(aa,bb,sizeof(aa))
using namespace std;
const int maxn=1000010;
int f[maxn];
int a[10],all,sum;
int q1[maxn],q2[maxn],l1,r1,l2,r2;

void work(){
    Set(f,0);
    all>>=1;
    int w,v,l,k;
    For(i,1,6){
        w=v=i;
        For(j,0,w-1){
            l1=l2=1,r1=r2=0;
            for(k=j,l=0;k<=all;++l,k+=w){
                if(r1-l1==a[i]){//以a[i]的大小取剩余类
                    if(q1[l1]==q2[l2]) ++l2;
                    ++l1;
                }
                int t=f[k]-l*v;//将全体都减去一个大小,放入单调队列中
                q1[++r1]=t;
                while(l2<=r2 && q2[r2]<t) --r2;
                q2[++r2]=t;
                f[k]=q2[l2]+l*v;//重新计算
            }
        }
    }
    if(f[all]==all) puts("Can be divided.");
    else puts("Can't be divided.");
    return ;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    while(1){
        all=0;
        For(i,1,6) scanf("%d",&a[i]),all+=a[i]*i;
        if(!all) break;
        ++sum;
        printf("Collection #%d:\n",sum);
        if(all&1){puts("Can't be divided.");puts("");continue;}
        work();
        puts("");
    }
    return 0;
}
Published 51 original articles · won praise 6 · views 20000 +

Guess you like

Origin blog.csdn.net/qq_35776579/article/details/54945856