[学習記録]AtCoder EDP D-Knapsack 1[Go]
問題
問題文
N 個の品物があります。 品物には 1,2,…,N と番号が振られています。 各 i (1≤i≤N) について、品物 i の重さは wi で、価値は vi です。
太郎君は、N 個の品物のうちいくつかを選び、ナップサックに入れて持ち帰ることにしました。 ナップサックの容量は W であり、持ち帰る品物の重さの総和は W 以下でなければなりません。
太郎君が持ち帰る品物の価値の総和の最大値を求めてください。
制約
入力はすべて整数である。
1≤N≤100
1≤W≤10^5
1≤wi≤W
1≤vi≤10^9
解法
i 番目までの品物を使って、重さ j になったときの、価値の最大値を記録する
for i := 1; i <= n; i++ {
for j := 1; j <= w; j++ {
// dpに記録
}
}
i 番目の品物を使うとき、使わないときそれぞれの値を計算し、それをdp に記録する。
使うときは、 i -1番目品物まで使い j - (i 番目の品物の重さ) の時の価値 に i番目の品物の価値を加えたものになる。
使わないときは、i -1番目まで使った時と同じ価値になる。
// 入れる
in := dp[i-1][j-weight] + value
// 入れない
not_in := dp[i-1][j]
dp[i][j] = Max(in, not_in)
j より品物の重さが大きいとき、その品物は使えない。そのため、ガードを追加する。
// そもそも入れられない
if weight > j {
// not_inと同じパターン
dp[i][j] = dp[i-1][j]
continue
}
i =1の時、i -1(=0)番目まで使った時の価値が必要になるため、
dpをn +1, w +1で初期化する
dp := make([][]int, n+1)
// ...
dp[i] = make([]int, w+1)
全て計算した後、dp[n]][w]が回答になる。
( n番目の品物まで使い、重さwとなったときの価値の最大値)
コード(AC)
func run() interface{} {
n, w := readInt(), readInt()
sli := make([][]int, n)
for i := 0; i < n; i++ {
sli[i] = readSli(2)
}
dp := make([][]int, n+1)
dp[0] = make([]int, w+1)
for i := 1; i <= n; i++ {
dp[i] = make([]int, w+1)
weight := sli[i-1][0]
value := sli[i-1][1]
for j := 1; j <= w; j++ {
// そもそも入れられない
if weight > j {
dp[i][j] = dp[i-1][j]
continue
}
// 入れる
in := dp[i-1][j-weight] + value
// 入れない
not_in := dp[i-1][j]
dp[i][j] = Max(in, not_in)
}
}
ans := dp[n][w]
return ans
}
この記事が気に入ったらサポートをしてみませんか?