ほぼ静的な計画法

競技プログラミングで解いた問題の解法とコードを晒していくページ。ややマイナーなC♯。

AOJ 0042 (A Thief : 泥棒)

【問題】

https://onlinejudge.u-aizu.ac.jp/problems/0042

http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0042

【解説】

いわゆる0-1ナップザック問題。

動的計画法にて解いていけばよい。漸化式や解説については、リンク先のwikipediaを参照。

dpテーブル"dp[w]"を用意し、添え字は風呂敷に入っている品物の重さとしている。これを、各品物の数の分だけ操作していく。dpテーブルに入れる値は、品物iの価値を\(v_i\)、重さを\(w_i\)とすると、要素jについて、 $$ dp[j] = \max (dp[j], dp[j - w_i] + v_i) (j - w_i ≧ 0) $$ となる。すなわち、風呂敷にその品物を入れられるだけの重さに余裕があれば、入れる前の価値に品物の価値を加えた値を求め、その値がその重さにおける価値を上回っていれば、値を更新する、ということになる。これを、配列の末尾から先頭に向かって処理していけばよい。

最後に全ての品物に対して処理した結果の配列の最大値をとれば、それが解となる。

配列を操作する場合に昇順で辿ってしまうと、同じ品物を複数入れてしまうことに注意する。

【コード】