問題
回答
TLEで間に合わない最初の回答
アルゴリズム的には合っているかな?
import sys # input処理を高速化する input = sys.stdin.readline # 入力 N, W = map(int, input().split()) # sum_vの取りうる上限値 MAX_V = (10**3+1) * N # 最小値を求めるので無限大の値 f_inf = float('inf') def chmin(a, b): if a <= b: return a else: return b def knapsack(n, w): # dpの初期化 dp[i][sum_v]は重さの総和の最小値 dp = [[f_inf for i in range(MAX_V)] for j in range(N+1)] # 初期条件 dp[0][0] = 0 # forは全て関数の中で回す。 # 入力 for i in range(N): w, v = map(int, input().split()) for sum_v in range(MAX_V): # i番目の品物を選ぶ場合 if (sum_v -v >= 0): dp[i + 1][sum_v] = chmin(dp[i + 1][sum_v], dp[i][sum_v - v] + w) # i番目の品物を選ばない場合 dp[i + 1][sum_v] = chmin(dp[i + 1][sum_v], dp[i][sum_v]) #dp[N][sum_v]の値が、W以下であるsum_vの値の最大値 ans = 0 for sum_v in range(MAX_V): if dp[N][sum_v] <= W: ans = sum_v print(ans) knapsack(N, W)
AC
少し絞るとACになる。
import sys # input処理を高速化する input = sys.stdin.readline # 入力 N, W = map(int, input().split()) # sum_vの取りうる上限値 MAX_V = (10**3) * N +1 # 最小値を求めるので無限大の値 f_inf = float('inf') def knapsack(n, w): # dpの初期化 dp[sum_v]は重さの総和の最小値 dp = [f_inf] * MAX_V # 初期条件 dp[0] = 0 sum_v = 0 # forは全て関数の中で回す。 # 入力 for i in range(N): w, v = map(int, input().split()) for j in range(MAX_V, v-1, -1): new_weight = dp[j - v] + w if new_weight > W: continue if dp[j] > new_weight: dp[j] = new_weight ans = 0 for sum_v in range(MAX_V): if dp[sum_v] <= W: ans = sum_v print(ans) knapsack(N, W)
numpyを使った回答
import sys import numpy as np # input処理を高速化する input = sys.stdin.readline # 入力 N, W = map(int, input().split()) # sum_vの取りうる上限値 MAX_V = (10**3) * N +1 def knapsack(n, w): # dp[i][j] : i番目の品物で価値jの重さの最小値 dp = np.full([N+1, MAX_V], np.inf) dp[0][0] = 0 for i in range(n): w, v = map(int, input().split()) dp[i+1] = dp[i] dp[i+1][v:] = np.minimum(dp[i][v:], dp[i][:-v] + w) print(np.max(np.where(dp <= W))) knapsack(N, W)