HDU2639 Bone Collector II 題解 0-1揹包的嚴格第k優解
阿新 • • 發佈:2020-09-09
題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=2639
題目大意:給出一行價值,一行體積,讓你在v體積的範圍內找出第k大的值.......(注意,不要 和它的第一題混起來,它第一行是價值,再是體積)
思路:首先dp[i][j]代表的是在體積為i的時候第j優解為 dp[i][j]
......那麼,我們就可以這樣思考,i
對應體積,那麼如果只是一維的 dp[i]
,代表的應該是體積為 i
時的最大值,那麼同理,dp[i][1]
代表的是體積為 i
時的最大值,那麼我們就可以退出兩種動態,dp[i][m],dp[i-s[i][0]][m]+s[i][1]
.....然後把這兩種狀態開個兩個陣列分別儲存起來,再合併出體積為i
k
優解......依次後推,直到dp[v][k]
.......
具體實現的時候,我令 \(f[i]\) 為一個 set 集合,這樣處理的話方面一些(然而也很麻煩)。
示例程式碼:
#include <bits/stdc++.h> using namespace std; const int maxn = 101, maxv = 1001; int T, n, V, K, c[maxn], v[maxn]; set<int> f[maxv]; void pack(int c, int v) { for (int i = V; i >= c; i --) { f[i].insert(v); for (set<int>::iterator it = f[i-c].begin(); it != f[i-c].end(); it ++) { f[i].insert((*it) + v); } int sz = f[i].size(); while (sz > K) { f[i].erase(f[i].begin()); sz --; } } } int main() { cin >> T; while (T --) { cin >> n >> V >> K; for (int i = 0; i <= V; i ++) f[i].clear(); f[0].insert(0); for (int i = 0; i < n; i ++) cin >> v[i]; for (int i = 0; i < n; i ++) cin >> c[i]; for (int i = 0; i < n; i ++) pack(c[i], v[i]); if (f[V].size() < K) puts("0"); else { set<int>::iterator it = f[V].end(); for (int i = 0; i < K; i ++) it --; cout << (*it) << endl; } } return 0; }