Knapsack Without Repetition
You are given n objects and a knapsack. Object i has an integer weight w[i] and an integer value v[i]. The knapsack has integer capacity B. You may put each object in the knapsack at most once (you cannot take fractions or duplicates). Design a dynamic-programming algorithm for the following task.
Two axes: which objects are available (i) and how much capacity remains (b). The capacity bound B becoming a table dimension is exactly why this is pseudo-polynomial.
Either skip object i (K(i−1, b)), or take it and add its value to the best packing of the remaining objects in the reduced capacity: v[i] + K(i−1, b−w[i]). Both branches drop to row i−1.
The "take" branch here is v[i] + K(i−1, b−w[i]) — dropping to row i−1 is what forbids reusing object i. In the with-repetition version (see 6.17) the same branch stays on row i: K(i, b−w[i]). This one index is the entire difference between the two Knapsacks. Read the problem for "at most once" vs. "unlimited supply" and pick accordingly.
O(nB) looks polynomial but isn't: B is a number whose input encoding has only log B bits, so the runtime is exponential in the input size. If the exam asks whether Knapsack has a polynomial-time algorithm, the honest answer is "this DP is pseudo-polynomial, not polynomial."
Optional pseudocode not required by Ed #9
A mechanical translation. The take-branch drops to row i-1 — that's what forbids reuse.
function Knapsack01(w[1..n], v[1..n], B): for b = 0 to B: K[0][b] = 0 for i = 1 to n: K[i][0] = 0 for b = 1 to B: if w[i] > b: K[i][b] = K[i-1][b] else: K[i][b] = max(K[i-1][b], v[i] + K[i-1][b-w[i]]) return K[n][B]
Try it yourself
worked example + self-testK(i,b)=max{K(i−1,b), v[i]+K(i−1,b−w[i])}. Answer K(n,B).
w = [1, 3, 4, 5] v = [1, 4, 5, 7] B = 7
2 (w3,v4) + 3 (w4,v5) = weight 7, value 9. (Greedy-by-ratio would pick items 1&4 for only 8 — the point.)w = [2, 3, 4, 6] v = [3, 4, 5, 8] B = 6