题目链接:
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;
}