题目链接:
HDU 2639 Bone Collector II
题意:
有n件物品,背包总容量V,每件物品的体积和价值分别为volume[i]和val[i],求背包可以容纳的第K大的总价值?
分析:
优先队列,将所有情况保存下来,然后取前K个。
//1612K 1170MS
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int MAX_N=110;
const int MAX_V=1010;
const int MAX_K=35;
int T,n,v,k;
int val[MAX_N],volume[MAX_N],dp[MAX_V][MAX_K];
int main()
{
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&v,&k);
for(int i=1;i<=n;i++) { scanf("%d",&val[i]); }
for(int i=1;i<=n;i++) { scanf("%d",&volume[i]); }
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
for(int j=v;j>=volume[i];j--){
priority_queue<int> Q;
for(int h=1;h<=k;h++){
if(dp[j][h]){
Q.push(dp[j][h]);
//printf("i=%d j=%d k=%d push: %d\n",i,j,k,dp[j][h].num);
}
Q.push(dp[j-volume[i]][h]+val[i]);
//printf("i=%d j=%d k=%d push: %d\n",i,j,k,dp[j-volume[i]][h].num+val[i]);
}
for(int h=1;h<=k;h++){
if(Q.empty()){
dp[j][h]=0;
//printf("case 1: i=%d j=%d h=%d dp[i][j][h]=%d\n",i,j,h,dp[i][j][h]);
}else {
int a,b;
a=b=Q.top();
Q.pop();
//去重
while(!Q.empty()&&a==b) {
b=Q.top();
Q.pop();
}
if(a!=b) {
Q.push(b);
//printf("b=%d\n",b);
}
dp[j][h]=a;
//printf("a=%d b=%d\n",a,b);
//printf("case 2: i=%d j=%d h=%d dp[i][j][h]=%d\n",i,j,h,dp[i][j][h]);
}
}
}
}
printf("%d\n",dp[v][k]);
}
return 0;
}