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

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;
}
✐☎博主撰文不易,转载还请注明出处;若对本文有疑,请私信或在下方讨论中提出。O(∩_∩)O谢谢!☏

☃〔尽管小伙伴们肯定有千百种方式针对,但博主还是极其非常十分不要脸的把反对键吃掉辣!〕☃

✿『$At$ $last$:非常一(hu)本(shuo)正(ba)经(dao)的:博主很笨,请不要欺负他』✿✍

原文地址:https://www.cnblogs.com/812-xiao-wen/p/10315710.html