問題
回答
最初にTLEで間に合わなかった回答
考え方としては合っているはず…。
import sys # inputを高速化する。 input = sys.stdin.readline # 入力 N, W = map(int, input().split()) lst_weight = [0 for _ in range(N)] lst_value = [0 for _ in range(N)] for i in range(N): lst_weight[i], lst_value[i] = map(int, input().split()) def chmax(a, b): if a >= b: return a else: return b dp = [[0 for i in range(W+1)] for j in range(N+1)] for i in range(N): for sum_w in range(W+1): # i番目の品物を選ぶ if sum_w - lst_weight[i] >= 0: dp[i+1][sum_w] = chmax(dp[i+1][sum_w], dp[i][sum_w - lst_weight[i]] + lst_value[i]) # i番目の品物を選ばない dp[i+1][sum_w] = chmax(dp[i+1][sum_w], dp[i][sum_w]) print(dp[N][W])
関数を使うと速くなる
他のコードを参考にして速度を上げるよう努力しました。最終的な分かれ道となったのは、処理を関数内に含めるかどうかです。
下の2つのコードは、処理を関数に含めるかどうかだけの違いですが、関数に含めるとACになります。
関数を使わないとTLE
import sys input = sys.stdin.readline N, W = map(int, input().split()) dp = [0] * (W + 1) for _ in range(N): w, v = map(int, input().split()) for wk in range(W, w-1, -1): tv = dp[wk - w] + v if tv > dp[wk]: dp[wk] = tv print(dp[-1])
関数を使うとAC
import sys input = sys.stdin.readline N, W = map(int, input().split()) dp = [0] * (W + 1) def knapsack(n, w): for _ in range(N): w, v = map(int, input().split()) for wk in range(W, w-1, -1): tv = dp[wk - w] + v if tv > dp[wk]: dp[wk] = tv return dp[-1] print(knapsack(N, W))
関数にすることで、変数がローカル変数として扱われるので処理速度が速くなります。
The Python Wiki PythonSpeed PerformanceTips Local Variables
なぜPythonのコードは関数の中では速くなるか? Why does Python code run faster in a function?
numpy を使った回答
numpy を使うとdpの行列を作って値を更新してくだけなので、 自分にとっては一番わかりやすい。
import sys import numpy as np # input処理を高速化する input = sys.stdin.readline # 入力 N, W = map(int, input().split()) def knapsack(n, w): # dp[i][j] : i番目の品物で重さj以下の価値の最大値 dp = np.zeros([N+1, W+1], dtype='int64') # forは関数の中で回す。 for i in range(N): w, v = map(int, input().split()) # i+1番目でwより小さい場合は、i番目と変更なし dp[i+1][:w] = dp[i][:w] dp[i+1][w:] = np.maximum(dp[i][w:], dp[i][:-w] + v) # print(dp) return dp[-1][-1] print(knapsack(N, W))