def knapsack(items, capacity): if type(capacity) is not int or capacity < 0: raise ValueError("Nonnegative integer capacity required") if any(not isinstance(name, str) or type(weight) is not int or weight <= 0 or type(value) is not int or value < 0 for name, weight, value in items): raise ValueError("Invalid named item") if len({name for name, _, _ in items}) != len(items): raise ValueError("Unique item names required") if (len(items) + 1) * (capacity + 1) > 100000: raise ValueError("Teaching table budget exceeded") table = [[0] * (capacity + 1) for _ in range(len(items) + 1)] for row, (_, weight, value) in enumerate(items, 1): for room in range(capacity + 1): table[row][room] = table[row - 1][room] if weight <= room: table[row][room] = max(table[row][room], value + table[row - 1][room - weight]) chosen, room = [], capacity for row in range(len(items), 0, -1): if table[row][room] != table[row - 1][room]: name, weight, _ = items[row - 1] chosen.append(name) room -= weight return table[-1][capacity], list(reversed(chosen)) items = [("net", 3, 7), ("crate", 2, 4), ("tag", 1, 2)] value, chosen = knapsack(items, 4) records = {name: (weight, score) for name, weight, score in items} weight = sum(records[name][0] for name in chosen) score = sum(records[name][1] for name in chosen) assert len(chosen) == len(set(chosen)) and weight <= 4 and score == value print(chosen) print(weight, score)