0-1ナップザック問題: カバンに入れる宝物を選ぼう
0-1ナップザック問題は、重さの制限があるカバンに、価値の高い品物をできるだけうまく入れる問題です。
各品物は「入れる」か「入れない」かのどちらかです。半分だけ入れることはできないので、0-1と呼ばれます。
使いどころ
- 限られた予算や容量で最大の成果を選ぶ問題
- 動的計画法の代表的な練習問題
- 「選ぶ・選ばない」の判断を表にして整理する問題
手順
dp[w]を「重さwまで使えるときの最大価値」と考える- 品物を1つずつ見る
- 入れられる重さなら、入れた場合と入れない場合を比べる
- 大きい価値を保存する
図で見る
コピペ用コード
def knapsack(items, capacity):
dp = [0] * (capacity + 1)
for weight, value in items:
for w in range(capacity, weight - 1, -1):
dp[w] = max(dp[w], dp[w - weight] + value)
return dp[capacity]
items = [(2, 3), (3, 4), (4, 5)]
print(knapsack(items, 5))
コードの読み方
dp[w]は、重さwまで使えるときの最大価値です。dp[w - weight] + valueは、その品物を入れた場合の価値です。range(capacity, weight - 1, -1)と逆順に見ることで、同じ品物を2回使わないようにしています。
注意点
逆順に更新するのが重要です。小さい重さから更新すると、同じ品物を何度も入れたことになってしまいます。