35 10 21 2 3 4 55 4 3 2 15 10 121 2 3 4 55 4 3 2 15 10 161 2 3 4 55 4 3 2 1 Sample Output1220 Authorteddy Source百万秦关终属楚题意:给出一行价值,一行体积,让你在v体积的范围内找出第k大的值;
思路:01背包的进一步优化,普通的背包是求得最大值;
需要求第k大,我们需要在dp数组上多开一维,记录v体积下第k大的值;
然后我们利用01背包思想将原值与新得到的值进行按大小合并;
代码:
#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int maxn=105;int dp[1010][50];int value[maxn],weight[maxn];int a[50],b[50];int n,V,K;void solve_dp(){ memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++) for(int j=V;j>=weight[i];j--) { for(int k=1;k<=K;k++) { a[k]=dp[j][k]; b[k]=dp[j-weight[i]][k]+value[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",&value[i]); for(int i=0;i<n;i++) scanf("%d",&weight[i]); solve_dp(); printf("%d/n",dp[V][K]); }}
新闻热点
疑难解答