AT_abc442_g [ABC442G] Lightweight Knapsack
来讲一下官解。
如果 \(K_i = 1\) 就是 CF808E,那题有神秘 DP 做法,感兴趣的可以去看看。
对于这题,肯定是要贪心的。有个显然的事情就是如果我们记重量为 \(w\) 的物品选了 \(F_w\) 个,那么我们肯定要贪心地选取 \(v\) 最大的那 \(F_w\) 个。
其次,我们可以将 \(6\) 个 \(w = 1\) 的物品,或 \(3\) 个 \(w = 2\) 的物品,或 \(2\) 个 \(w = 3\) 的物品合并成一个 \(w = 6\) 的物品,合并带来的好处就是,我们不需要跑背包了,而是可以直接贪心地选取,因为 \(w\) 都是相同的。
但是现在问题是 \(F_1\) 不一定是 \(6\) 的倍数, \(w = 2, 3\) 同理,所以可能会有多出来的物品。无妨,我们假设 \(F_i \equiv R_i \pmod{\frac{6}{i}}\),即 \(F_1 \equiv R_1 \pmod 6\),\(F_2 \equiv R_2 \pmod 3\),\(F_3 \equiv R_3 \pmod 2\),那么我们优先把 \(v\) 前 \(R_i\) 大的拿出来,剩下的合并即可。时间复杂度 \(\mathcal{O}(n \log nC)\),其中 \(C = \prod\limits_{i=1}^3 \frac{6}{i} = 36\)。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
// typedef __int128 i128;
typedef pair<ll, ll> pll;
const int N = 2e5 + 10, mod = 998244353;
template<typename T>
void dbg(const T &t) { cout << t << endl; }
template<typename Type, typename... Types>
void dbg(const Type& arg, const Types&... args) {
cout << arg << ' ';
dbg(args...);
}
namespace Loop1st {
int n;
ll c, ans;
pair<ll, vector<pll>> merge(vector<pll> ls, int r, int g) { // 去掉最后 r 个,剩下的每 g 个合并成一组
ll t = 0;
while (r && !ls.empty()) {
auto [v, k] = ls.back();
if (k > r) { t += v * r; ls.back().second -= r; break; }
t += v * k;
r -= k;
ls.pop_back();
}
vector<pll>res;
ll cnt = 0, sum = 0;
while (!ls.empty()) {
auto [v, k] = ls.back();
ls.pop_back();
if (cnt) {
if (cnt + k < g) {
cnt += k;
sum += v * k;
continue;
}
k -= g - cnt;
sum += v * (g - cnt);
res.emplace_back(sum, 1);
cnt = sum = 0;
}
if (k >= g) res.emplace_back(v * g, k / g);
cnt = k % g;
sum = v * cnt;
}
return {t, res};
}
void main() {
vector<vector<pll>> ls(4);
cin >> n >> c;
for (int i = 0; i < n; i++) {
ll w, v, k; cin >> w >> v >> k;
ls[w].emplace_back(v, k);
}
for (int w = 1; w <= 3; w++) sort(ls[w].begin(), ls[w].end());
for (int p = 0; p < 6; p++) {
auto [t1, g1] = merge(ls[1], p, 6);
for (int q = 0; q < 3; q++) {
auto [t2, g2] = merge(ls[2], q, 3);
for (int r = 0; r < 2; r++) {
// dbg("###", p, q, r);
auto [t3, g3] = merge(ls[3], r, 2);
ll m = c - p - q * 2 - r * 3;
if (m < 0) continue;
m /= 6;
ll sum = t1 + t2 + t3;
auto g = g1;
g.insert(g.end(), g2.begin(), g2.end());
g.insert(g.end(), g3.begin(), g3.end());
sort(g.begin(), g.end());
while (!g.empty()) {
auto [v, k] = g.back();
if (k >= m) { sum += v * m; break; }
m -= k;
sum += v * k;
g.pop_back();
}
ans = max(ans, sum);
}
}
}
cout << ans << '\n';
}
}
int main() {
// freopen("data.in", "r", stdin);
// freopen("data.out", "w", stdout);
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T = 1;
// cin >> T;
while (T--) Loop1st::main();
return 0;
}

浙公网安备 33010602011771号