白準12865号:普通リュック
1509 ワード
問題解決の考え方ダイナミックプログラミング 分割不可リュック問題(リュック問題)
✔アルゴリズムの説明
夜勤は苦悶して、どうしても考えが浮かばず、アルゴリズムそのものを勉強しようと決心した.次の図は、与えられた例を求めるプロセスを示す直接描画です.
(N+1)x(K+1)寸法を宣言する2次元配列で、デフォルト値はいずれも0です.この場合,赤色に塗った方は実際には不要な数字であるが,コードの一般化のために別途定義する.
ドアがN回回ったので、一つ一つのものの重さと価値が得られました.このとき「どのような判断」をして順番に並べます.(以下、この部分について詳しく説明します.)左の黒い字に書かれた数字は1つのものの重さで、円に書かれた値は物の価値です.便宜上、重量の小さい値からミント色→青→青→紫色の順に充填すると仮定します.
N番の各ケースにおいて、物品の重量の合計が1〜K(本例では7)の各重量においてとり得る最大値を算出する.このとき、「今まで」のものだけを判断します.(DP)
上記の「いかなる判断」は以下の通りである.
Case 1:新しく来たものの重量が現在利用可能な重量(1からKまで変化)より大きいと入れられないので、上図の矢印のように、以前の最低価格をそのまま持ってきます.
Case 2:物を入れることができる場合は、2つの値を比較し、最大値を入れます.
1つは、自身を入れない前の最大値であり、もう1つは、自身を残りの重量に入れて最大化したときの値である.このとき、残重量を最大化すると、算出された値が利用される.
✔実現コードの困難なアルゴリズムに比べて、コードは想像以上に簡単です.以上詳しく説明したので,これ以上説明しないようにした. コア点火式
dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight]+value)
✔関連概念動的プログラミングにおけるリュックサック問題
夜勤は苦悶して、どうしても考えが浮かばず、アルゴリズムそのものを勉強しようと決心した.次の図は、与えられた例を求めるプロセスを示す直接描画です.
(N+1)x(K+1)寸法を宣言する2次元配列で、デフォルト値はいずれも0です.この場合,赤色に塗った方は実際には不要な数字であるが,コードの一般化のために別途定義する.
ドアがN回回ったので、一つ一つのものの重さと価値が得られました.このとき「どのような判断」をして順番に並べます.(以下、この部分について詳しく説明します.)左の黒い字に書かれた数字は1つのものの重さで、円に書かれた値は物の価値です.便宜上、重量の小さい値からミント色→青→青→紫色の順に充填すると仮定します.
N番の各ケースにおいて、物品の重量の合計が1〜K(本例では7)の各重量においてとり得る最大値を算出する.このとき、「今まで」のものだけを判断します.(DP)
上記の「いかなる判断」は以下の通りである.
Case 1:新しく来たものの重量が現在利用可能な重量(1からKまで変化)より大きいと入れられないので、上図の矢印のように、以前の最低価格をそのまま持ってきます.
Case 2:物を入れることができる場合は、2つの値を比較し、最大値を入れます.
1つは、自身を入れない前の最大値であり、もう1つは、自身を残りの重量に入れて最大化したときの値である.このとき、残重量を最大化すると、算出された値が利用される.
import sys
N, K = map(int, sys.stdin.readline().split())
dp = [[0]*(K+1) for _ in range(N+1)]
for i in range(1, N+1):
weight, value = map(int, sys.stdin.readline().split())
for j in range(1, K+1):
if weight > j:
dp[i][j] = dp[i-1][j]
else:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight]+value)
print(dp[N][K])
dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight]+value)
✔関連概念
Reference
この問題について(白準12865号:普通リュック), 我々は、より多くの情報をここで見つけました https://velog.io/@dlehdtjq00/백준-12865번-평범한-배낭テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol