Source code for titan_pylib.others.knapsack_solver

 1from bisect import bisect_right
 2
 3
[docs] 4class KnapsackSolver: 5 6 def __init__(self, N: int, W: int, VW: list[tuple[int, int]]): 7 self.N: int = N 8 self.W: int = W 9 self.VW: list[tuple[int, int]] = VW 10
[docs] 11 def solve_hanbunzenrekkyo(self) -> int: 12 def naive(vw): 13 ret = [] 14 n = len(vw) 15 for i in range(1 << n): 16 value, weight = 0, 0 17 for j in range(n): 18 if i >> j & 1: 19 value += vw[j][0] 20 weight += vw[j][1] 21 ret.append([weight, value]) 22 return ret 23 24 left, right = self.VW[: self.N // 2], self.VW[self.N // 2 :] 25 left_ret = naive(left) 26 left_ret.sort() 27 right_ret = naive(right) 28 right_ret.sort() 29 for i in range(len(right_ret) - 1): 30 right_ret[i + 1][1] = max(right_ret[i + 1][1], right_ret[i][1]) 31 ans = -1 32 W = self.W 33 for weight, value in left_ret: 34 if weight > W: 35 break 36 i = bisect_right(right_ret, [W - weight, float("inf")]) - 1 37 ans = max(ans, value + right_ret[i][1]) 38 return ans
39
[docs] 40 def solve_dp_small_weight(self): 41 dp = [-1] * (self.W + 1) 42 W = self.W 43 dp[0] = 0 44 for i, (v, w) in enumerate(self.VW): 45 ep = [-1] * (W + 1) 46 for j in range(W + 1): 47 if dp[j] == -1: 48 continue 49 ep[j] = max(ep[j], dp[j]) 50 if j + w <= W: 51 ep[j + w] = max(ep[j + w], dp[j] + v) 52 dp = ep 53 return max(dp)
54
[docs] 55 def solve_dp_small_value(self) -> int: 56 sum_v = sum(v for v, _ in self.VW) 57 inf = float("inf") 58 dp = [inf] * (sum_v + 1) 59 dp[0] = 0 60 for v, w in self.VW: 61 ep = [inf] * (sum_v + 1) 62 for j in range(sum_v + 1): 63 if dp[j] == inf: 64 continue 65 ep[j] = min(ep[j], dp[j]) 66 if j + v <= sum_v: 67 ep[j + v] = min(ep[j + v], dp[j] + w) 68 dp = ep 69 for j in range(sum_v, -1, -1): 70 if dp[j] <= self.W: 71 return j 72 return -1