本文共 3329 字,大约阅读时间需要 11 分钟。
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4739 Accepted Submission(s): 2470
题目大意:
见之前的收集骨头的博客,题意类似,给定背包容量,骨头的个数和每个骨头的价值,这次不是求在背包容量允许的情况下,最多装的价值,而是求在背包容量内,可以装的第k大价值,如果没有第k个最大值,那么输出0
输入包括多组样例,第一行输入一个T,样例的个数,接下来每个样例都有三行,第一行包括三个整数,N,V,K,分别代表骨头的个数,背包的容量,我们需要输出的第K个最大值,第二行包括N个数,分别代表骨头的数量和接下来一行有N个数,分别表示每种骨头的价值。
输出第K个最大价值,每个样例输出一行
思路:简单的01背包基础上做,要求的是第K个最大值,那么不用dp[j]=max(dp[j],dp[j-w[i]]+v[i])的状态转移方程,而是将两个值都记录下来,用for循环走一遍,记录下,容量为1到M的各个最大价值,dp[i][j]表示当背包容量为i时的第j个最大价值,最后只需要输出dp[m][k]即可!
下面给出AC代码:
1 #include2 using namespace std; 3 int w[110]; 4 int v[110]; 5 int dp[1010][35]; 6 int d1[1010]; 7 int d2[1010]; 8 int main() 9 {10 int t,n,m,k,x,y,z,p;11 scanf("%d",&t);12 while(t--)13 {14 memset(w,0,sizeof(w));15 memset(v,0,sizeof(v));16 memset(dp,0,sizeof(dp));17 memset(d1,0,sizeof(d1));18 memset(d2,0,sizeof(d2));19 scanf("%d%d%d",&n,&m,&k);20 for(int i=1;i<=n;i++)21 scanf("%d",&v[i]);22 for(int i=1;i<=n;i++)23 scanf("%d",&w[i]);24 for(int i=1;i<=n;i++)//01背包变形25 {26 for(int j=m;j>=w[i];j--)27 {28 for(p=1;p<=k;p++)29 {30 d1[p]=dp[j][p];31 d2[p]=dp[j-w[i]][p]+v[i];32 }33 d1[p]=d2[p]=-1;34 x=y=z=1;35 while((d1[x]!=-1||d2[y]!=-1)&&z<=k)36 {37 if(d1[x]>d2[y])38 {39 dp[j][z]=d1[x];40 x++;41 }42 else43 {44 dp[j][z]=d2[y];45 y++;46 }47 if(dp[j][z-1]!=dp[j][z])48 z++;49 }50 }51 }52 printf("%d\n",dp[m][k]);53 }54 return 0;55 }
转载地址:http://iytta.baihongyu.com/