結果

問題 No.2866 yuusaan's Knapsack
ユーザー InTheBloomInTheBloom
提出日時 2024-08-30 22:35:09
言語 C++23(gcc13)
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 745 ms / 2,000 ms
コード長 2,358 bytes
コンパイル時間 1,361 ms
コンパイル使用メモリ 125,668 KB
実行使用メモリ 7,296 KB
最終ジャッジ日時 2024-08-31 01:29:04
合計ジャッジ時間 12,865 ms
ジャッジサーバーID
(参考情報)
judge5 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,812 KB
testcase_01 AC 2 ms
6,944 KB
testcase_02 AC 2 ms
6,940 KB
testcase_03 AC 2 ms
6,940 KB
testcase_04 AC 2 ms
6,940 KB
testcase_05 AC 1 ms
6,944 KB
testcase_06 AC 644 ms
6,940 KB
testcase_07 AC 457 ms
6,944 KB
testcase_08 AC 666 ms
6,940 KB
testcase_09 AC 568 ms
6,940 KB
testcase_10 AC 516 ms
6,940 KB
testcase_11 AC 371 ms
6,940 KB
testcase_12 AC 512 ms
6,944 KB
testcase_13 AC 442 ms
6,944 KB
testcase_14 AC 497 ms
6,940 KB
testcase_15 AC 555 ms
6,944 KB
testcase_16 AC 442 ms
6,944 KB
testcase_17 AC 684 ms
7,168 KB
testcase_18 AC 335 ms
6,944 KB
testcase_19 AC 650 ms
6,940 KB
testcase_20 AC 511 ms
7,040 KB
testcase_21 AC 591 ms
6,944 KB
testcase_22 AC 497 ms
6,944 KB
testcase_23 AC 745 ms
7,296 KB
testcase_24 AC 418 ms
6,944 KB
testcase_25 AC 607 ms
6,944 KB
testcase_26 AC 3 ms
6,944 KB
testcase_27 AC 2 ms
6,940 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <numeric>
#include <algorithm>
#include <vector>
#include <map>

using namespace std;
using ll = long long;

constexpr int iINF = 1'000'000'000;

int main () {
    int N, W; cin >> N >> W;

    vector<int> v(N), w(N);
    for (int i = 0; i < N; i++) cin >> v[i] >> w[i];

    // テーブル範囲外に溢れた後にテーブル範囲内に戻ってくる遷移に気を付ければ普通のナップサックになる。
    // mapで持って、先にマイナスから処理することにする。

    vector<int> index(N);
    iota(index.begin(), index.end(), 0);
    sort(index.begin(), index.end(), [&] (int a, int b) { return w[a] < w[b]; });

    const ll MOD = 998244353;

    map<int, int> dp, ndp;
    map<int, int> c, nc;
    // dp[i] := 重さiで達成できる最大価値
    // c[i] := その時点で重さiで達成できる最大価値を作る場合の数
    dp[0] = 0;
    c[0] = 1;

    for (int p = 0; p < N; p++) {
        int i = index[p];
        ndp.clear();
        nc.clear();

        for (auto e : dp) {
            { // 取らない
                int pre = -iINF;
                if (ndp.find(e.first) != ndp.end()) pre = ndp[e.first];
                ndp[e.first] = max(pre, e.second);
            }

            // とる
            if (e.first + w[i] <= W) {
                int pre = -iINF;
                if (ndp.find(e.first + w[i]) != ndp.end()) pre = ndp[e.first + w[i]];
                ndp[e.first + w[i]] = max(pre, e.second + v[i]);
            }
        }

        // 場合の数の方の更新
        for (auto e : dp) {
            // 取らない
            if (ndp[e.first] == dp[e.first]) {
                nc[e.first] += c[e.first];
                nc[e.first] %= MOD;
            }

            // とる
            if (e.first + w[i] <= W) {
                if (ndp[e.first + w[i]] == dp[e.first] + v[i]) {
                    nc[e.first + w[i]] += c[e.first];
                    nc[e.first + w[i]] %= MOD;
                }
            }
        }

        swap(dp, ndp);
        swap(c, nc);
    }

    int max_value = 0;
    for (auto e : dp) max_value = max(max_value, e.second);

    ll count = 0;
    for (auto e : dp) if (max_value == e.second) {
        count += c[e.first];
        count %= MOD;
    }

    cout << max_value << " " << count << "\n";
}
0