前提・実現したいこと
リストの初期化の方法が異なると、同じコードを実行しても異なる出力が得られるのですが、挙動が異なる理由がわかりません。
一見同じように機能するように思える二つの初期化方法で、なぜ一方は不適当な動作をするのか、教えていただけないでしょうか?
問題:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_1_B&lang=jp
(秋葉ほか『プログラミングコンテストチャレンジブック』 p.52)
発生している問題・エラーメッセージ
次のようにdpを初期化すると、計算時、各行の列成分が同一になります。
初期化コードと問題ある出力
Python3
1dp = [[0] * (W + 1)] * N + [[0] * (W + 1)] #正しく出力しない 2[[0, 2, 5, 8, 10, 13], 3 [0, 2, 5, 8, 10, 13], 4 [0, 2, 5, 8, 10, 13], 5 [0, 2, 5, 8, 10, 13], 6 [0, 0, 0, 0, 0, 0]] 7#一番下の行を除いて、すべての行で列成分が同じになる
正しいdpの出力と対応するコード(入力例 1)
dp = [[0] * (W + 1) for i in range(N + 1)] #正しく出力する [[0, 2, 5, 8, 10, 13], [0, 2, 5, 8, 10, 13], [0, 2, 2, 8, 10, 10], [0, 0, 0, 8, 8, 8], [0, 0, 0, 0, 0, 0]]
該当のソースコード
Python3
1import pprint 2 3N, W = map(int, input().split()) 4w = [0] * (N + 1) 5v = [0] * (N + 1) 6for _ in range(N): 7 v[_], w[_] = map(int, input().split()) 8 9dp = [[0] * (W + 1)] * (N + 1) 10 11 12dp = [[0] * (W + 1)] * N + [[0] * (W + 1)] 13#dp = [[0] * (W + 1) for i in range(N + 1)] 14dp[N][W] = 0 15 16for i in range(N - 1, -1, -1): 17 for j in range(W + 1): 18 # 重量オーバー 19 if j < w[i]: 20 dp[i][j] = dp[i + 1][j] 21 # jよりw[i]が小さい場合: 入れないとき・入れるときの価値を比較し最大値 22 else: 23 dp[i][j] = max(dp[i + 1][j], dp[i + 1][j - w[i]] + v[i]) 24 25 26pprint.pprint(dp) 27
入力例1
上記の出力は次の入力に対するものです。
4 5
4 2
5 2
2 1
8 3
補足情報(FW/ツールのバージョンなど)
Python3.7 anacondaを使用
01ナップザック問題を動的計画法で解くプログラムを組んでいます。ここでは配列dp[i][j]を、「i番目以降の品物から重さの総和がj以下になるように選んだ商品の価値の総和」としています。そのため、dp[i][j]の数値は各行でそれぞれ異なっているはずです。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/04/10 13:15
2020/04/10 14:13
2020/04/11 04:57