#include <bits/stdc++.h>
using namespace std;
/*
NOI 2018 - Knapsack (Task 2)
Complexity:
- Let S <= 2000.
- Grouping and sorting per weight: O(T log T), T = total truncated copies = O(S log S).
- DP: O(T * S) ~ O(S^2 log S).
- Memory: O(S).
*/
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int S, N;
if (!(cin >> S >> N)) {
return 0;
}
// group[w] holds values of items of weight w (with multiplicities,
// but we will truncate later).
vector<vector<long long>> group(S + 1);
for (int i = 0; i < N; ++i) {
long long V;
int W;
long long K;
cin >> V >> W >> K;
if (W > S) continue; // can never be taken
// Maximum useful copies of this item by capacity:
long long max_copies = S / W;
if (max_copies == 0) continue;
long long take = min(K, max_copies);
// Instead of doing binary splitting, just push 'take' copies of V
// into group[W]; we'll truncate after merging all items of weight W.
// Since we will finally keep at most floor(S / W) total values for this weight,
// this push may overfill but truncation will fix it.
// However, to avoid pathological overpush when many items share same weight,
// we can cap per item too:
if (take > 0) {
// But we still must be careful of large 'take' (up to 2000).
// It is fine to push directly since S<=2000.
for (long long c = 0; c < take; ++c) {
group[W].push_back(V);
}
}
}
// For each weight, keep only the best floor(S / w) values.
for (int w = 1; w <= S; ++w) {
if (group[w].empty()) continue;
int limit = S / w;
if ((int)group[w].size() > limit) {
// partial sort to get top 'limit' values
nth_element(group[w].begin(), group[w].begin() + limit, group[w].end(),
greater<long long>());
group[w].resize(limit);
}
}
// 1D 0/1 knapsack DP
vector<long long> dp(S + 1, 0);
for (int w = 1; w <= S; ++w) {
if (group[w].empty()) continue;
// For each copy as a separate 0/1 item
for (long long v : group[w]) {
// standard 0/1 knapsack transition, descending over weight
for (int curW = S; curW >= w; --curW) {
long long cand = dp[curW - w] + v;
if (cand > dp[curW]) dp[curW] = cand;
}
}
}
long long ans = 0;
for (int w = 0; w <= S; ++w) {
if (dp[w] > ans) ans = dp[w];
}
cout << ans << '\n';
return 0;
}
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |