n_toshi max_t p1,1 p1,2 ・・・ p1,max_t // 1 番目の投資先によって得られる利益 p2,1 p2,2 ・・・ p2,max_t // 2 番目の投資先によって得られる利益 ・・・ pn_toshi,1 pn_toshi,2 ・・・ pn_toshi,max_t
3 4 8 18 22 24 // 1 番目の投資先に 1 単位投資するとその利益は 8,2 単位投資するとその利益は 18,・・・ 3 6 9 12 // 2 番目の投資先に 1 単位投資するとその利益は 3,2 単位投資するとその利益は 6,・・・ 6 7 8 10 // ・・・
4 6 2 0 0 0 0 0 // 1 番目の品物の重さは 1 で,その効用は 2 0 0 5 0 0 0 // 2 番目の品物の重さは 3 で,その効用は 5 0 0 4 0 0 0 // 3 番目の品物の重さは 3 で,その効用は 4 0 0 3 0 0 0 // 4 番目の品物の重さは 3 で,その効用は 3
#**************************************************/ # 動的計画法:資源配分問題(0-1 ナップザック問題)*/ # ー投資先(品物)毎のデータを出力したい場合ー */ # coded by Y.Suganuma */ #**************************************************/ # データの入力と領域の確保 a = (gets().strip()).split() n_toshi = Integer(a[0]) # 投資先数(品物数) max_t = Integer(a[1]) # 最大投資額(最大重量) max_t += 1 # 投資を行わない(品物を入れない)場合を含めるため table = Array.new(n_toshi) # 投資額と利益(重さと効用) rieki = Array.new(n_toshi) # 投資した際の利益(品物を入れた際の効用) prev = Array.new(n_toshi) # 前段までの投資額(前段までの重さ) for i1 in Range.new(0, n_toshi, true) table[i1] = Array.new(max_t) rieki[i1] = Array.new(max_t) prev[i1] = Array.new(max_t) end for i1 in Range.new(0, n_toshi, true) table[i1][0] = 0 a = (gets().strip()).split() for i2 in Range.new(1, max_t, true) table[i1][i2] = Integer(a[i2-1]) end end # 動的計画法 # 初期設定(1段目) for i1 in Range.new(0, max_t, true) rieki[0][i1] = table[0][i1] prev[0][i1] = -1 end # 2段目以降 for i1 in Range.new(1, n_toshi, true) for i2 in Range.new(0, max_t, true) rieki[i1][i2] = rieki[i1-1][i2] prev[i1][i1] = prev[i1-1][i2] end for i2 in Range.new(0, max_t, true) i3 = 0 while i2+i3 < max_t if rieki[i1-1][i3]+table[i1][i2] > rieki[i1][i2+i3] rieki[i1][i2+i3] = rieki[i1-1][i3]+table[i1][i2] prev[i1][i2+i3] = i3 end i3 += 1 end end end # 結果の出力 k = -1 max = -1 for i1 in Range.new(0, max_t, true) if rieki[n_toshi-1][i1] > max max = rieki[n_toshi-1][i1] k = i1 end end printf("最大利益(最大効用) %d\n", max) #i1 = n_toshi-1 #while i1 > 0 for i1 in Range.new(n_toshi-1, 0, true).step(-1) k1 = 0 if rieki[i1][k] != rieki[i1-1][k] k1 = k - prev[i1][k] k = prev[i1][k] end printf(" 投資先(品物) %d 投資単位(重さ) %d 利益(効用) %d\n", (i1+1), k1, table[i1][k1]) # i1 -= 1 end printf(" 投資先(品物) 1 投資単位(重さ) %d 利益(効用) %d\n", k, table[0][k])
#**************************************************/ # 動的計画法:資源配分問題(0-1 ナップザック問題)*/ # ー投資先(品物)毎のデータを必要としない場合ー */ # coded by Y.Suganuma */ #**************************************************/ # データの入力と領域の確保 a = (gets().strip()).split() n_toshi = Integer(a[0]) # 投資先数(品物数) max_t = Integer(a[1]) # 最大投資額(最大重量) max_t += 1 # 投資を行わない(品物を入れない)場合を含めるため table = Array.new(n_toshi) # 投資額と利益(重さと効用) rieki = Array.new(2) # 投資した際の利益(品物を入れた際の効用) for i1 in Range.new(0, n_toshi, true) table[i1] = Array.new(max_t) end for i1 in Range.new(0, 2, true) rieki[i1] = Array.new(max_t) end for i1 in Range.new(0, n_toshi, true) table[i1][0] = 0 a = (gets().strip()).split() for i2 in Range.new(1, max_t, true) table[i1][i2] = Integer(a[i2-1]) end end # 動的計画法 # 初期設定(1段目) k1 = 0 k2 = 1 for i1 in Range.new(0, max_t, true) rieki[0][i1] = table[0][i1] rieki[1][i1] = 0 end # 2段目以降 for i1 in Range.new(1, n_toshi, true) for i2 in Range.new(0, max_t, true) rieki[k2][i2] = rieki[k1][i2] end for i2 in Range.new(0, max_t, true) i3 = 0 while i2+i3 < max_t if rieki[k1][i3]+table[i1][i2] > rieki[k2][i2+i3] rieki[k2][i2+i3] = rieki[k1][i3]+table[i1][i2] end i3 += 1 end end k1 += 1 k1 %= 2 k2 += 1 k2 %= 2 end # 結果の出力 max = -1 for i1 in Range.new(0, max_t, true) if rieki[k1][i1] > max max = rieki[k1][i1] end end printf("最大利益(最大効用) %d\n", max)
N W w1 v1 // 1 番目の品物の重さとそれを入れた場合の効用 w2 v2 // 2 番目の品物の重さとそれを入れた場合の効用 ・・・ wN vN
4 6 1 2 3 5 3 4 3 3
#**************************************/ # 動的計画法(0-1ナップザック問題) */ # ー品物毎のデータを出力したい場合ー */ # coded by Y.Suganuma */ #**************************************/ # データの入力と領域の確保 a = (gets().strip()).split() N = Integer(a[0]) # 品物の数 W = Integer(a[1]) # 重さの上限 w = Array.new(N) # 各品物の重さ v = Array.new(N) # 各品物の効用 for i1 in Range.new(0, N, true) a = (gets().strip()).split() w[i1] = Integer(a[0]) v[i1] = Integer(a[1]) end # 動的計画法 # 初期設定(1段目) prev = Array.new(N) # 前段までの品物の重さ dp = Array.new(N) # ナップザック内の品物の重さ for i1 in Range.new(0, N, true) prev[i1] = Array.new(W+1) dp[i1] = Array.new(W+1) end for i1 in Range.new(0, W+1, true) dp[0][i1] = -1 prev[0][i1] = -1 end if w[0] <= W dp[0][w[0]] = v[0] end # 2段目以降 for i1 in Range.new(1, N, true) for wt in Range.new(0, W+1, true) dp[i1][wt] = dp[i1-1][wt] prev[i1][wt] = prev[i1-1][wt] end # 最初の品物である場合 if w[i1] <= W and dp[i1][w[i1]] < v[i1] dp[i1][w[i1]] = v[i1] prev[i1][w[i1]] = 0 end # 過去に品物が入っている場合 for wt in Range.new(1, W+1, true) if dp[i1-1][wt] > 0 and wt+w[i1] <= W if dp[i1-1][wt]+v[i1] > dp[i1][wt+w[i1]] dp[i1][wt+w[i1]] = dp[i1-1][wt] + v[i1] prev[i1][wt+w[i1]] = wt end end end end # 結果の出力 k = -1 ans = -1 for i1 in Range.new(0, W+1, true) if dp[N-1][i1] > ans ans = dp[N-1][i1] k = i1 end end printf("最大効用 %d\n", ans) for i1 in Range.new(N-1, 0).step(-1) k1 = 0 if dp[i1][k] != dp[i1-1][k] k1 = k - prev[i1][k] k = prev[i1][k] end vv = v[i1] if k1 <= 0 vv = 0 end printf(" 品物 %d 重さ %d 効用 %d\n", (i1+1), k1, vv) end vv = v[0] if k <= 0 vv = 0 end printf(" 品物 1 重さ %d 効用 %d\n", k, vv)
#****************************************/ # 動的計画法(0-1ナップザック問題) */ # ー品物毎のデータを必要としない場合ー */ # coded by Y.Suganuma */ #****************************************/ # データの入力と領域の確保 a = (gets().strip()).split() N = Integer(a[0]) # 品物の数 W = Integer(a[1]) # 重さの上限 w = Array.new(N) # 各品物の重さ v = Array.new(N) # 各品物の効用 for i1 in Range.new(0, N, true) a = (gets().strip()).split() w[i1] = Integer(a[0]) v[i1] = Integer(a[1]) end # 動的計画法 # 初期設定(1段目) dp = Array.new(2) # ナップザック内の品物の重さ for i1 in Range.new(0, 2, true) dp[i1] = Array.new(W+1) end for i1 in Range.new(0, W+1, true) dp[0][i1] = -1 dp[1][i1] = -1 end if w[0] <= W dp[0][w[0]] = v[0] end k1 = 0 k2 = 1 # 2段目以降 for i1 in Range.new(1, N, true) for wt in Range.new(0, W+1, true) dp[k2][wt] = dp[k1][wt] end # 最初の品物である場合 if w[i1] <= W and dp[k2][w[i1]] < v[i1] dp[k2][w[i1]] = v[i1] end # 過去に品物が入っている場合 for wt in Range.new(1, W+1, true) if dp[k1][wt] > 0 and wt+w[i1] <= W if dp[k1][wt]+v[i1] > dp[k2][wt+w[i1]] dp[k2][wt+w[i1]] = dp[k1][wt] + v[i1] end end end k1 += 1 k1 %= 2 k2 += 1 k2 %= 2 end # 結果の出力 ans = 0 for i1 in Range.new(0, W+1, true) if dp[k1][i1] > ans ans = dp[k1][i1] end end printf("最大効用 %d\n", ans)
N M // ノードの数,接続データの数(接続データが無いノード間は移動できない) ni nj rij // ノード ni と ノード nj 間の距離は rij ・・・
7 10 0 1 2 0 2 5 1 2 4 1 3 6 1 4 10 2 3 2 3 5 1 4 5 3 4 6 5 5 6 9
#******************************************/ # 動的計画法(グラフにおける最短距離問題)*/ # ー経路を出力したい場合ー */ # coded by Y.Suganuma */ #******************************************/ # データの入力と領域の確保 a = (gets().strip()).split() N = Integer(a[0]) # ノードの数 M = Integer(a[1]) # 接続状況データ数 r = Array.new(N) # ノード間の距離 for i1 in Range.new(0, N, true) r[i1] = Array.new(N) for i2 in Range.new(0, N, true) r[i1][i2] = 0 end end for i1 in Range.new(0, M, true) a = (gets().strip()).split() k1 = Integer(a[0]) k2 = Integer(a[1]) r[k1][k2] = Integer(a[2]) end for i1 in Range.new(0, N-1, true) for i2 in Range.new(i1+1, N, true) r[i2][i1] = r[i1][i2] end end # 動的計画法 # 初期設定(1段目) prev = Array.new(N) # 前のノード dp = Array.new(N) # ノードへ達するまでの距離 for i1 in Range.new(0, N, true) prev[i1] = Array.new(N) dp[i1] = Array.new(N) for i2 in Range.new(0, N, true) prev[i1][i2] = -1 dp[i1][i2] = -1 end end dp[0][0] = 0 # 2段目以降 n = 0 sw = 1 while sw > 0 sw = 0 for i1 in Range.new(0, N, true) dp[n+1][i1] = dp[n][i1] prev[n+1][i1] = prev[n][i1] end for i1 in Range.new(0, N, true) for i2 in Range.new(0, N, true) if dp[n][i1] >= 0 and r[i1][i2] > 0 if dp[n+1][i2] < 0 or (dp[n][i1]+r[i1][i2] < dp[n+1][i2]) dp[n+1][i2] = dp[n][i1] + r[i1][i2] prev[n+1][i2] = i1 sw = 1 end end end end if sw > 0 n += 1 end end # 結果の出力 printf("最短距離 %d\n", dp[n][N-1]) k = N - 1 printf(" ノード番号 %d\n", k) while n > 0 printf(" ノード番号 %d\n", prev[n][k]) k = prev[n][k] n -= 1 end
#******************************************/ # 動的計画法(グラフにおける最短距離問題)*/ # ー経路を出力する必要が無い場合ー */ # coded by Y.Suganuma */ #******************************************/ # データの入力と領域の確保 a = (gets().strip()).split() N = Integer(a[0]) # ノードの数 M = Integer(a[1]) # 接続状況データ数 r = Array.new(N) # ノード間の距離 for i1 in Range.new(0, N, true) r[i1] = Array.new(N) for i2 in Range.new(0, N, true) r[i1][i2] = 0 end end for i1 in Range.new(0, M, true) a = (gets().strip()).split() k1 = Integer(a[0]) k2 = Integer(a[1]) r[k1][k2] = Integer(a[2]) end for i1 in Range.new(0, N-1, true) for i2 in Range.new(i1+1, N, true) r[i2][i1] = r[i1][i2] end end # 動的計画法 # 初期設定(1段目) dp = Array.new(2) # ノードへ達するまでの距離 for i1 in Range.new(0, 2, true) dp[i1] = Array.new(N) for i2 in Range.new(0, N, true) dp[i1][i2] = -1 end end dp[0][0] = 0 # 2段目以降 sw = 1 k1 = 0 k2 = 1 while sw > 0 sw = 0 for i1 in Range.new(0, N, true) dp[k2][i1] = dp[k1][i1] end for i1 in Range.new(0, N, true) for i2 in Range.new(0, N, true) if dp[k1][i1] >= 0 and r[i1][i2] > 0 if dp[k2][i2] < 0 or (dp[k1][i1]+r[i1][i2] < dp[k2][i2]) dp[k2][i2] = dp[k1][i1] + r[i1][i2] sw = 1 end end end end if sw > 0 k1 += 1 k1 %= 2 k2 += 1 k2 %= 2 end end # 結果の出力 printf("最短距離 %d\n", dp[k1][N-1])