*洛谷P1858 多人背包
题目描述
求01背包前k优解的价值和
输入输出格式
输入格式:
第一行三个数K、V、N
接下来每行两个数,表示体积和价值
输出格式:
前k优解的价值和
输入输出样例
输入样例#1:
2 10 5 3 12 7 20 2 4 5 6 1 1
输出样例#1:
57
/*背包九讲中第九讲明确给出求次小值及第k小值的办法,做两个队列,b1,b2,用于储存选这个物品和不选这个物品的最大价值,然后取最大值进行合并(类似归并排序)*/ #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define maxn 5020 int n,m,k,v[maxn],w[maxn],a[maxn],b[maxn],dp[maxn][maxn]; int main(){ scanf("%d%d%d",&k,&m,&n); for(int i=1;i<=n;i++)scanf("%d%d",&w[i],&v[i]); memset(dp, -0x7f, sizeof dp); dp[0][1] = 0; for(int i=1;i<=n;i++){ for(int j=m;j>=w[i];j--){ int lena=0,lenb=0; for(int h=1;h<=k;h++){ a[++lena]=dp[j][h]; b[++lenb]=dp[j-w[i]][h]+v[i]; } int toa=1,tob=1; for(int h=1;h<=k;h++){ if(a[toa]>b[tob]&&toa<=lena)dp[j][h]=a[toa++]; else dp[j][h]=b[tob++]; } } } int ans=0; for(int i=1;i<=k;i++)ans+=dp[m][i]; cout<<ans; }