Knapsack Algorithm
Knapsack Algorithm
Furthermore, in T
We can create a new binary tree T′ by swapping the positions of the branches
rooted at v and w in T. This is depicted in Figure 4.12. It is not hard to see from
Equality 4.3 and the previous two inequalities that
Figure 4.12 The branches rooted at v and w are swapped.
which means the code corresponding to T′ is optimal. Clearly, the set of trees
obtained in the (i + 1)st step of Huffman’s algorithm are branches in T′.
where wi, pi, and W are positive integers. Determine a subset A of S such that
The brute-force solution is to consider all subsets of the n items; discard those
subsets whose total weight exceeds W; and, of those remaining, take one with
maximum total profit. Example A.10 in Appendix A shows that there are 2n
subsets of a set containing n items. Therefore, the brute-force algorithm is
exponential-time.
An obvious greedy strategy is to steal the items with the largest profit first;
that is, steal them in nonincreasing order according to profit. This strategy,
however, would not work very well if the most profitable item had a large
weight in comparison to its profit. For example, suppose we had three items, the
first weighing 25 pounds and having a profit of $10, and the second and third
each weighing 10 pounds and having a profit of $9. If the capacity W of the
knapsack was 30 pounds, this greedy strategy would yield only a profit of $10,
whereas the optimal solution is $18.
Another obvious greedy strategy is to steal the lightest items first. This
strategy fails badly when the light items have small profits compared with their
weights.
To avoid the pitfalls of the previous two greedy algorithms, a more
sophisticated greedy strategy is to steal the items with the largest profit per unit
weight first. That is, we order the items in nonincreasing order according to
profit per unit weight, and select them in sequence. An item is put in the
knapsack if its weight does not bring the total weight above W. This approach is
illustrated in Figure 4.13. In that figure, the weight and profit for each item are
listed by the item, and the value of W, which is 30, is listed in the knapsack. We
have the following profits per unit weight:
Figure 4.13 A greedy solution and an optimal solution to the 0-1 Knapsack problem.
Ordering the items by profit per unit weight yields
As can be seen in the figure, this greedy approach chooses item1 and item3,
resulting in a total profit of $190, whereas the optimal solution is to choose item2
and item3, resulting in a total profit of $200. The problem is that after item1 and
item3 are chosen, there are 5 pounds of capacity left, but it is wasted because
item2 weighs 10 pounds. Even this more sophisticated greedy algorithm does not
solve the 0-1 Knapsack problem.
Our greedy algorithm never wastes any capacity in the Fractional Knapsack
problem as it does in the 0-1 Knapsack problem. As a result, it always yields an
optimal solution. You are asked to prove this in the exercises.
The maximum profit is equal to P [n] [W]. We can determine this value using a
two-dimensional array P whose rows are indexed from 0 to n and whose
columns are indexed from 0 to W. We compute the values in the rows of the
array in sequence using the previous expression for P [i] [w]. The values of P [0]
[w] and P [i] [0] are set to 0. You are asked to actually write the algorithm in the
exercises. It is straightforward that the number of array entries computed is
Example 4.9
Suppose we have the items in Figure 4.13 and W = 30. First we determine which
entries are needed in each row.
Compute row 1:
Therefore,
Compute row 2:
Compute row 3:
This version of the algorithm computes only seven entries, whereas the
original version would have computed (3) (30) = 90 entries.
Let’s determine how efficient this version is in the worst case. Notice that we
compute at most 2i entries in the (n − i)th row. Therefore, at most the total
number of entries computed is
Combining these two results, we can conclude that the worst-case number of
entries computed is in
The previous bound is in terms of only n. Let’s also obtain a bound in terms of
n and W combined. We know that the number of entries computed is in O (nW),
but perhaps this version avoids ever reaching this bound. This is not the case. In
the exercises you will show that if n = W + 1 and wi = 1 for all i, then the total
number of entries computed is about
The first equality is obtained in Example A.1 in Appendix A, and the second
derives from the fact that n = W +1 in this instance. Therefore, this bound is
reached for arbitrarily large values of n and W, which means the worst-case
number of entries computed is in
We do not need to create the entire array to implement the algorithm. Instead, we
can store just the entries that are needed. The entire array exists only implicitly.
If the algorithm is implemented in this manner, the worst-case memory usage
has these same bounds.
We could write a divide-and-conquer algorithm using the expression for P [i]
[w] that was used to develop the dynamic programming algorithm. For this
algorithm the worst-case number of entries computed is also in Θ(2n). The main
advantage of the dynamic programming algorithm is the additional bound in
terms of nW. The divide-and-conquer algorithm does not have this bound.
Indeed, this bound is obtained because of the fundamental difference between
dynamic programming and divide-and-conquer. That is, dynamic programming
does not process the same instance more than once. The bound in terms of nW is
very significant when W is not large in comparison with n.
As is the case for the Traveling Salesperson problem, no one has ever found
an algorithm for the 0-1 Knapsack problem whose worst-case time complexity is
better than exponential, yet no one has proven that such an algorithm is not
possible. Such problems are the focus of Chapter 9.
EXERCISES
Sections 4.1
1. Show that the greedy approach always finds an optimal solution for the
Change problem when the coins are in the denominations D0, D1, D2, … , Di
for some integers i > 0 and D > 0.
2. Use Prim’s algorithm (Algorithm 4.1) to find a minimum spanning tree for
the following graph. Show the actions step by step.