多人背包 (二维背包维护次优解)
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;
}