多人背包 (二维背包维护次优解)

solution:

在进行01背包转移时,同时转移维护多个次优解即可。合并时要用到归并思想(不能二分插入)。

code:

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>

#define ll long long
#define db double
#define inf 0x7fffffff
#define rg register int

using namespace std;

int k,m,n,ans,b[55];
int a[205],v[205];
int f[5005][55];
int h[5005];

inline int qr(){
    char ch;
    while((ch=getchar())<'0'||ch>'9');
    int res=ch^48;
    while((ch=getchar())>='0'&&ch<='9')
        res=res*10+(ch^48);
    return res;
}

inline void merge(int x,int y,int z){
    rg i=1,j=1,o=0;
    while(i<=h[x]&&j<=h[y]&&o<=k){
        while(f[x][i]+z>=f[y][j]&&i<=h[x]&&o<=k)
            b[++o]=f[x][i]+z,++i;
        while(f[x][i]+z<=f[y][j]&&j<=h[y]&&o<=k)
            b[++o]=f[y][j],++j;
    }
    while(i<=h[x]&&o<=k)b[++o]=f[x][i]+z,++i;
    while(j<=h[y]&&o<=k)b[++o]=f[y][j],++j;
    for(h[y]=o;o>0;--o)
        f[y][o]=b[o];
}

int main(){
    //freopen("bags.in","r",stdin);
    //freopen("bags.out","w",stdout);
    k=qr(),m=qr(),n=qr();h[0]=1;
    for(rg i=1;i<=n;++i)
        a[i]=qr(),v[i]=qr();
    for(rg i=1;i<=n;++i)
        for(rg j=m;j>=a[i];--j)
            merge(j-a[i],j,v[i]);
    for(rg i=1;i<=k;++i)
        ans+=f[m][i];
    printf("%d",ans);
    return 0;
}
posted @ 2019-01-24 17:20  一只不咕鸟  阅读(154)  评论(0编辑  收藏  举报