题目大意:
给定3个数n,m,k,分别代表有n个骨头,m大的背包,求解第k大的价值。
以下两行分别代表,价值和体积。
思路:定义两个数组a,b来分别存dp[j-v[i]][t]+p[i],和dp[j][t],其中dp[j][t],代表体积为j的包能装的第t大价值。
最后再合并到dp数组中,求解前K大只需要将前K个数求解出来,放入dp中。
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> #include<math.h> #include<queue> #define ll long long #define inf 1000010+10 using namespace std; int p[1010],v[1010],a[1010],b[1010]; int dp[1010][1010]; int main() { int n,m,i,j,k; int cla; scanf("%d",&cla); while(cla--) { scanf("%d%d%d",&n,&m,&k); for(i=1;i<=n;i++) scanf("%d",&p[i]); for(i=1;i<=n;i++) scanf("%d",&v[i]); memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++) { for(j=m;j>=v[i];j--) { for(int t=1;t<=k;t++) { a[t]=dp[j][t]; b[t]=p[i]+dp[j-v[i] ][t]; } a[k+1]=b[k+1]=-1;//注意不要漏掉 int x=1,y=1,z=1; while(z<=k&& (x<=k||y<=k )) { if(a[x]>b[y]) { dp[j][z]=a[x]; x++; } else { dp[j][z]=b[y],y++; } if(dp[j][z]!=dp[j][z-1]) { z++; } } } } printf("%d\n",dp[m][k]); } return 0; }