01背包的转移方程为
dp[j]=max(dp[j],dp[j-vol[i]+cost[i]]);
因为要求解第k大的解
需要用二位数组储存
即dp[j][k];
j为体积 k为第几优的解
所以保存下转移过程中dp[j]与dp[j-vol[i]]的前k大的值
dp[j]与dp[j-vol[i]]两个状态中一共有k*2个值取其中前k大的数赋值与dp[j]中;
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <malloc.h>
#include <ctype.h>
#include <math.h>
#include <string>
#include<iostream>
#include <algorithm>
using namespace std;
#define MAXN 100*111
#include <queue>
#include <vector>
#define IN freopen("in.txt","r",stdin);
int dp[1111][33],a[101],b[101],ans[333];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int n,t,v,k;
// IN;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&v,&k);
memset(dp,0,sizeof(dp));
for(int i=0; i<n; i++)
scanf("%d",&a[i]);
for(int i=0; i<n; i++)
scanf("%d",&b[i]);
int tot=0;
for(int i=0; i<n; i++)
{
for(int j=v; j>=b[i]; j--)
{
tot=0;
memset(ans,0,sizeof(ans));
for(int p=0;p<k;p++)
{
ans[tot++]=dp[j][p];
ans[tot++]=dp[j-b[i]][p]+a[i];
}
sort(ans,ans+tot,cmp);
unique(ans,ans+tot);//去重
for(int p=0;;p++)
if(ans[p]==0)
{
for(int q=p+1;q<=61;q++)
ans[q]=0;
break;
}
for(int p=0;p<k;p++)
{
dp[j][p]=ans[p];
}
}
}
printf("%d\n",dp[v][k-1]);
}
return 0;
}