这道题求的是:01背包的第K优解。
意思是:容量为V的背包,能装的物品价值由大到小排序,第K大的是?
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
#define M 102
struct shop{
int cost[M],value[M];
}p;
int dp[1001][35],N,V,K;
/**
* 01背包求第K优解,意思是,容量为V的背包,能装的物品价值由大到小排序,
*第K大的是?
*其中f[v][k]表示i个物品、背包大小为v时,第k优解的值。
*/
int zeroOnePack()
{
int i,j,k;
int c1[35],c2[35];
memset(dp,0,sizeof(dp));
for(i = 0 ; i < N ; i++)
for(j = V ; j >=p.cost[i]; j--)
{
for(k=1;k<=K;k++)
{
c1[k]=dp[j-p.cost[i]][k]+p.value[i];
c2[k]=dp[j][k];//前i-1的前K最优解
}
//下面将两个有序(从大到小)的序列合并到dp[j][k](1<k<30)
int x=1,y=1,cnt=0;
c1[K+1]=0;c2[K+1]=0;
while(cnt<=K&&(x<=K||y<=K))
{
if(c1[x]>c2[y])
{
if(c1[x]!=dp[j][cnt])
dp[j][++cnt]=c1[x];
x++;
}
else
{
if(c2[y]!=dp[j][cnt])
dp[j][++cnt]=c2[y];
y++;
}
}
}
return dp[V][K];
}
void show()
{
for(int i=1;i<=K;i++)
printf("%d ",dp[V][i]);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&N,&V,&K);
for(int i = 0 ; i < N ; i++)
scanf("%d",&p.value[i]);
for(int i = 0 ; i < N ; i++)
scanf("%d",&p.cost[i]);
cout<<zeroOnePack()<<endl;
// show();
}
return 0;
}