hdu-2639 Bone Collector II 背包第K优
http://acm.hdu.edu.cn/showproblem.php?pid=2639
在背包的基础上维护一个size<=K的最大值集合,为什么维护K个就好了呢,因为如果当前状态有多余K个最优解,前K个就足够转移到下一状态并占满前K了,所以K个之后的都没必要维护。
#include <iostream> #include <cstdio> #include <vector> #include <string> #include <map> #include <queue> #include <set> #define LL long long using namespace std; const LL N=1005; set<LL> dp[N]; LL w[N]; LL v[N]; LL n,V,k; int main() { cin.sync_with_stdio(false); int t; cin>>t; while(t--) { cin>>n>>V>>k; for(int i=0; i<=V; i++)dp[i].clear(),dp[i].insert(0); for(int i=0; i<n; i++) cin>>v[i]; for(int i=0; i<n; i++) cin>>w[i]; for(int i=0; i<n; i++) { for(int j=V; j-w[i]>=0; j--) { int e=j-w[i]; for(set<LL>::iterator it=dp[e].begin();it!=dp[e].end();it++) { LL now=*it+v[i]; if(dp[j].size()==k) { if(now>*(dp[j].begin())) dp[j].erase(*dp[j].begin()),dp[j].insert(now); } else dp[j].insert(now); } } } if(dp[V].size()<k)cout<<0<<endl; else cout<<*dp[V].begin()<<endl; } return 0; }