标签:chm cep mis mon its new chmod bit input
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 #include <bits/stdc++.h> 2 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 else 43 { 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 }
HDU 2639 Bone Collector II(01背包变形【第K大最优解】)
标签:chm cep mis mon its new chmod bit input
原文地址:http://www.cnblogs.com/ECJTUACM-873284962/p/6820574.html