求每个状态里的k优解,然后合并
/* HDU 2639 求01背包的第k大解。 合并两个有序序列 */ #include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> using namespace std; const int MAXN=110; int dp[1010][50];//dp[i][j]表示容量为i,第j大的值 int value[MAXN]; int weight[MAXN]; int a[50]; int b[50]; int N,V,K; void DP() { memset(dp,0,sizeof(dp)); for(int i=0;i<N;i++) for(int j=V;j>=value[i];j--) { for(int k=1;k<=K;k++) { a[k]=dp[j][k]; b[k]=dp[j-value[i]][k]+weight[i]; } int x,y,z; x=y=z=1; a[K+1]=b[K+1]=-1;//这个一定要 while(z<=K&&(x<=K||y<=K))//合并两个已经排好序的序列 { if(a[x]>b[y])dp[j][z]=a[x++];//注意相同的只算一个 else dp[j][z]=b[y++]; if(dp[j][z]!=dp[j][z-1])z++; } } } 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",&weight[i]); for(int i=0;i<N;i++)scanf("%d",&value[i]); DP(); printf("%d ",dp[V][K]); } return 0; }