結果

問題 No.2866 yuusaan's Knapsack
ユーザー InTheBloomInTheBloom
提出日時 2024-08-30 22:35:09
言語 C++23
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 692 ms / 2,000 ms
コード長 2,358 bytes
コンパイル時間 1,494 ms
コンパイル使用メモリ 125,640 KB
実行使用メモリ 7,296 KB
最終ジャッジ日時 2024-09-26 14:37:16
合計ジャッジ時間 13,018 ms
ジャッジサーバーID
(参考情報)
judge3 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 26
権限があれば一括ダウンロードができます

ソースコード

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