제출 #1291854

#제출 시각아이디문제언어결과실행 시간메모리
1291854atharva0300Knapsack (NOI18_knapsack)C++20
73 / 100
372 ms327680 KiB
#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 timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...