多重背包的单调队列优化

https://blog.csdn.net/flyinghearts/article/details/5898183

完美的讲解

POJ2392

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;
#define endl "
"
#define inf 0x3f3f3f3f
#define me(a,b) memset(a,b,sizeof(a))
const int maxn=1005;
const int MAX_V = 400004;

pair<int,int> q[MAX_V];
inline void pack(int f[], int V, int v, int n, int w) {
    if (n == 0 || v == 0)
        return;
    if (n == 1) {               //01背包
        for (int i = V; i >= v; --i)
            if (f[i] < f[i - v] + w)
                f[i] = f[i - v] + w;
        return;
    }
    if (n * v >= V - v + 1) {
        for (int i = v; i <= V; ++i)
            if (f[i] < f[i - v] + w)
                f[i] = f[i - v] + w;
        return;
    }
    for(int j=0;j<v;j++){
        int head=1,rear=1;
        for(int k=j,i=0;k<=V;k+=v,i++){
            int tt=f[k]-i*w;
            while(rear!=head&&q[rear].first<tt) --rear;
            q[++rear]=make_pair(tt,i);
            if(head!=rear&&(i-q[head+1].second)>n) ++head;
            f[k]=q[head+1].first+i*w;
        }
    }
}
int f[40000+5];
int n;
int h[maxn],a[maxn],c[maxn];
int p[maxn];
bool cmp(int x,int y) {
    return a[x]<a[y];
}
int main() {
    cin>>n;
    for(int i=1; i<=n; i++)
        scanf("%d%d%d",&h[i],&a[i],&c[i]),p[i]=i;
    sort(p+1,p+n+1,cmp);
    for(int i=1; i<=n; i++) {
        int t=p[i];
        pack(f,a[t],h[t],c[t],h[t]);
    }
    printf("%d",*max_element(f,f+a[p[n]]+1));
}

  

原文地址:https://www.cnblogs.com/033000-/p/10477373.html