原题: http://acm.hdu.edu.cn/showproblem.php?pid=2639
在01背包上多加一维 [k] 表示该状态的第k个最优解
#include<stdio.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m,k;
int v[101];
int w[101];
scanf("%d %d %d",&n,&m,&k);
for(int i=0;i<n;i++)
{
scanf("%d",&v[i]);
}
for(int i=0;i<n;i++)
{
scanf("%d",&w[i]);
}
int dp[1010][31]={0};
for(int i=0;i<n;i++)
{
for(int j=m;j>=w[i];j--)//01背包
{
int q1[31];
int q2[31];
for(int kk=1;kk<=k;kk++)//得到两个子状态的子序列 本来只取最大我们是dp[j]=max(dp[j-w[i]]+v[i],dp[j]);
{
q1[kk]=dp[j-w[i]][kk]+v[i];
q2[kk]=dp[j][kk];
}
int c1,c2;
c1=c2=1;
int c=1;
q1[k+1]=q2[k+1]=-1;// 避免访问到不改访问的值
while(c<=k && (c1<=k || c2<=k))//合并两个子序列,取前k个最大
{
if(q1[c1]>q2[c2])
{
dp[j][c]=q1[c1++];
}else{
dp[j][c]=q2[c2++];
}
if(dp[j][c]!=dp[j][c-1])//根据题意,去掉重复
{
c++;
}
}
}
}
printf("%d\n",dp[m][k]);
}
return 0;
}