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

本文探讨了01背包问题中处理多个次优解的策略,使用归并思想而非二分插入来合并解集,通过示例代码详细展示了如何在01背包问题中维护和更新解集合。

AumMvD.png

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;
}

转载于:https://www.cnblogs.com/812-xiao-wen/p/10315710.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值