結果
| 問題 | No.3401 Large Knapsack Problem |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-11-27 13:30:31 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.89.0) |
| 結果 |
AC
|
| 実行時間 | 27 ms / 2,000 ms |
| コード長 | 2,577 bytes |
| 記録 | |
| コンパイル時間 | 2,617 ms |
| コンパイル使用メモリ | 284,164 KB |
| 実行使用メモリ | 10,868 KB |
| 最終ジャッジ日時 | 2025-12-07 23:30:05 |
| 合計ジャッジ時間 | 4,348 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 42 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
long long W;
if (!(cin >> N >> W)) return 0;
const int MAXW = 1000;
// 重さごとに最大価値を残す
vector<int> bestV(MAXW + 1, 0);
for (int i = 0; i < N; ++i) {
int v, w;
cin >> v >> w;
if (v > bestV[w]) bestV[w] = v;
}
// 支配される品物を削る(重さ昇順で価値が前より大きいものだけ残す)
vector<pair<int,int>> items; // (w, v)
int maxv = 0;
for (int w = 1; w <= MAXW; ++w) {
int v = bestV[w];
if (v > 0 && v > maxv) {
items.emplace_back(w, v);
maxv = v;
}
}
if (items.empty()) {
cout << 0 << '\n';
return 0;
}
// w_max(全品物の最大重さ)
int w_max = 0;
for (auto &p : items) w_max = max(w_max, p.first);
// 価値密度が最大の品物(同率なら重さが小さい方)
int w_best = items[0].first;
int v_best = items[0].second;
for (auto &p : items) {
int w = p.first;
int v = p.second;
long long lhs = 1LL * v * w_best;
long long rhs = 1LL * v_best * w;
if (lhs > rhs || (lhs == rhs && w < w_best)) {
w_best = w;
v_best = v;
}
}
long long Lll = 1LL * w_best * w_max; // L = w_best * w_max <= 250000
int B = (int)min(W, Lll); // DP する最大重さ
const long long NEG = -(1LL << 60);
vector<long long> dp(B + 1, NEG);
dp[0] = 0;
// 完全ナップサック DP(重さ 0..B)
for (auto &p : items) {
int wi = p.first;
int vi = p.second;
for (int w = wi; w <= B; ++w) {
if (dp[w - wi] == NEG) continue;
long long cand = dp[w - wi] + vi;
if (cand > dp[w]) dp[w] = cand;
}
}
long long ans = 0;
if (W <= B) {
// 容量が小さいときは普通に dp[0..W] を見る
for (int w = 0; w <= (int)W; ++w) {
if (dp[w] == NEG) continue;
if (dp[w] > ans) ans = dp[w];
}
} else {
// 容量が大きいときは補題を使って「base + 最優品」で詰める
for (int s = 0; s <= B; ++s) {
if (dp[s] == NEG) continue;
long long extra = (W - s) / w_best;
long long val = dp[s] + extra * (long long)v_best;
if (val > ans) ans = val;
}
}
cout << ans << '\n';
return 0;
}