def unbounded_knapsack(W, wt, val, n): dp = [0] * (W + 1) for i in range(W + 1): for j in range(n): if wt[j] <= i: dp[i] = max(dp[i], dp[i - wt[j]] + val[j]) return dp[W] W = 8 wt = [2, 3, 5] val = [15, 20, 50] n = len(wt) print(unbounded_knapsack(W, wt, val, n))
The function uses dynamic programming to find the maximum value for weight 8.
By choosing the 5-weight item once (value 50) and the 3-weight item once (value 20), total weight is 8 and value is 70.
But better is choosing the 3-weight item twice (20+20=40) and the 2-weight item twice (15+15=30), total value 70.
Actually, the best is choosing the 5-weight item once (50) and the 2-weight item once (15), total 65.
After checking all combinations, the maximum value is 70.
Unbounded knapsack means you can pick any item multiple times as long as total weight does not exceed capacity.
Option B correctly states this.
Option B describes fractional knapsack, which is different.
Option B is false because capacity is limited.
Option B is false because items can be chosen multiple times, not just once.
def unbounded_knapsack(W, wt, val, n): dp = [[0] * (W + 1)] * (n + 1) for i in range(1, n + 1): for w in range(1, W + 1): if wt[i-1] <= w: dp[i][w] = max(val[i-1] + dp[i][w - wt[i-1]], dp[i-1][w]) else: dp[i][w] = dp[i-1][w] return dp[n][W] W = 5 wt = [1, 3, 4] val = [10, 40, 50] n = len(wt) print(unbounded_knapsack(W, wt, val, n))
The dp table is initialized with dp = [[0] * (W + 1)] * (n + 1), which creates shallow copies of the same list.
Updating dp[i][w] changes multiple rows simultaneously, causing incorrect results.
The output is 60, which happens to be correct, but due to the shallow copy.
Correct initialization should use a list comprehension to create independent rows.
def unbounded_knapsack_recursive(W, wt, val, n, memo): if W == 0: return 0 if W in memo: return memo[W] max_val = 0 for i in range(n): if wt[i] <= W: max_val = max(max_val, val[i] + unbounded_knapsack_recursive(W - wt[i], wt, val, n, memo)) memo[W] = max_val return max_val W = 7 wt = [1, 3, 4] val = [10, 40, 50] n = len(wt) memo = {} print(unbounded_knapsack_recursive(W, wt, val, n, memo))
Possible combinations:
- 7 items of weight 1: 7*10=70
- 2 items of weight 3 + 1 item of weight 1: 2*40 + 10 = 90
- 1 item of weight 4 + 1 item of weight 3: 50 + 40 = 90
- 1 item of weight 4 + 3 items of weight 1: 50 + 30 = 80
Best is 90.
The code returns 90 correctly.
The DP solution uses two nested loops: one over weights from 0 to W, and one over n items.
Each dp[i] is computed by checking all n items.
Thus, time complexity is O(n * W).
Option A is exponential, incorrect.
Option A is higher than needed.
Option A is linear, incorrect.
