[AtCoder] Educational DP Contest D – Knapsack 1
問題
方針
いわゆるナップザック問題ですね。
\( d(i, j) \) を品物 \( i \) まで調べたとき、重さの総和が \( j \) であるときの価値の総和の最大値とします。初期値は、\( d(0, 0) = 0 \) で、それ以外は \( d(i, j) = -1 \) とします。遷移は次のようになります。
- \( d(i, j) \neq -1\) のとき
品物\( i \) を持ち帰ることを考えると、
\[d(i +1, j + w[i]) = \max(d(i + 1, j + w[i]), d(i, j) + v[i])\]
となり、品物を持ち帰らないとすると、
\[d(i +1, j) = \max(d(i + 1, j), d(i, j))\]
となります。よって、答えは、\(d(N, \cdot)\) の最大値となります。
コード
#include <bits/stdc++.h> using namespace std; typedef long long ll; int main() { int N, W; cin >> N >> W; ll w[N], v[N]; for (int i = 0; i < N; i++) { cin >> w[i] >> v[i]; } ll dp[N + 1][W + 1]; for (int i = 0; i <= N; i++) { for (int j = 0; j <= W; j++) { dp[i][j] = -1; } } dp[0][0] = 0; for (int i = 0; i < N; i++) { for (int j = 0; j <= W; j++) { int g = j + w[i]; if (dp[i][j] == -1) continue; dp[i + 1][j] = max(dp[i + 1][j], dp[i][j]); if (g > W) continue; dp[i + 1][g] = max(dp[i + 1][g], dp[i][j] + v[i]); } } ll ans = 0; for (int i = 0; i <= W; i++) { ans = max(ans, dp[N][i]); } cout << ans << "\n"; return 0; }
ディスカッション
コメント一覧
まだ、コメントがありません