27.03.2013 Views

CSci 231 Homework 7 Solutions - Bowdoin College

CSci 231 Homework 7 Solutions - Bowdoin College

CSci 231 Homework 7 Solutions - Bowdoin College

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>CSci</strong> <strong>231</strong> <strong>Homework</strong> 7 <strong>Solutions</strong> ∗<br />

Dynamic Programming and Greedy Algorithms<br />

CLRS Chapter 15 and 16<br />

Use a (single) separate sheet of paper for each problem. Be concise.<br />

1. A game-board consists of a row of n fields, each consisting of two numbers. The first<br />

number can be any positive integer, while the second is 1, 2, or 3. An example of a<br />

board with n = 6 could be the following:<br />

17 2 100 87 33 14<br />

1 2 3 1 1 1<br />

The object of the game is to jump from the first to the last field in the row. The top<br />

number of a field is the cost of visiting that field. The bottom number is the maximal<br />

number of fields one is allowed to jump to the right from the field. The cost of a game<br />

is the sum of the costs of the visited fields.<br />

Let the board be represented in a two-dimensional array B[n, 2]. The following recursive<br />

procedure (when called with argument 1) computes the cost of the cheapest<br />

game:<br />

Cheap(i)<br />

END Cheap<br />

IF i>n THEN return 0<br />

x=B[i,1]+Cheap(i+1)<br />

y=B[i,1]+Cheap(i+2)<br />

z=B[i,1]+Cheap(i+3)<br />

IF B[i,2]=1 THEN return x<br />

IF B[i,2]=2 THEN return min(x,y)<br />

IF B[i,2]=3 THEN return min(x,y,z)<br />

∗ Collaboration is allowed and encouraged, if it is constructive and helps you study better. Remember,<br />

exams will be individual. List the names of the collaborators with the solutions.


(a) Analyze the asymptotic running time of the procedure.<br />

Solution:<br />

T (n) = T (n − 1) + T (n − 2) + T (n − 3) + Θ(1)<br />

≥ 3 T (n − 3)<br />

= 3 2 T (n − 6)<br />

= . . .<br />

= 3 k T (n − 3k)<br />

≥ 3 n/3<br />

= Ω(3 n/3 ).<br />

(b) Describe and analyze a more efficient algorithm for finding the cheapest game.<br />

Solution: We create a table T of size n in which to store our results of prior<br />

runs. The modified algorithm would be as follows:<br />

Cheap(i)<br />

END Cheap<br />

IF T[i] != ∅ THEN return T[i]<br />

IF i>n THEN return 0<br />

x=B[i,1]+Cheap(i+1)<br />

y=B[i,1]+Cheap(i+2)<br />

z=B[i,1]+Cheap(i+3)<br />

IF B[i,2]=1 THEN T[i] = x<br />

IF B[i,2]=2 THEN T[i] = min(x,y)<br />

IF B[i,2]=3 THEN T[i] = min(x,y,z)<br />

return T[i]<br />

The cost of a recursive call is O(1) and we fill each entry in the table at most<br />

once, so the running time is O(n).<br />

2


2. In this problem we consider the 0-1 knapsack problem: Given n items, with item<br />

i being worth v[i] dollars and having weight w[i] pounds, fill a knapsack of capacity m<br />

pounds with the maximal possible value.<br />

Example: Given a knapsack of capacity 50, the maximal value obtainable<br />

with three items of value $60, $100, and $120 and weights 10, 20, and 30,<br />

respectively, is $220.<br />

$60<br />

10<br />

$100<br />

20<br />

Items in value<br />

per pound<br />

order<br />

$120<br />

30<br />

30<br />

20<br />

= $220<br />

Optimal solution<br />

for knapsack of<br />

size 50<br />

20<br />

10<br />

= $160<br />

Greedy solution<br />

for knapsack of<br />

size 50<br />

The algorithm Knapsack(i,j) below returns the maximal value obtainable when filling<br />

a knapsack of capacity j using items among items 1 through i (Knapsack(n,m)<br />

solves our problem). The algorithm works by recursively computing the best solution<br />

obtainable with the last item and the best solution obtainable without the last item,<br />

and returning the best of them.<br />

Knapsack(i,j)<br />

IF w[i]


Solution:<br />

(a) Following the hint, if w[i] = 1 then it is clear that T (n, m) > 2T (n − 1, m −<br />

1) + 1. This recurrence, which runs for min(m, n) steps, gives that T (n, m) =<br />

Ω(2 min(m,n) ).<br />

(b) We create a table of size [n][m] in which to store our results of prior runs. The<br />

modified algorithm would be as follows:<br />

Knapsack(i,j)<br />

END<br />

IF table[i][j] != 0 THEN<br />

RETURN table[i][j]<br />

IF w[i]


3. Imagine now that the items in the problem above are such that you can take fractions<br />

of items. With this modified condition, the problem is called the Fractional<br />

Knapsack problem. Identify a greedy strategy to solve the problem. Prove that<br />

this strategy correctly identifies an optimal solution for all possible inputs.<br />

Analyse the running time of your algorithm and compare it with the 0-1 knapsack<br />

problem running time.<br />

Does it pay off being greedy (in this case)?<br />

Solution: Let v[i] and w[i] denote the weight and value of item i, respectively.<br />

Compute for each item the price per pound vp[i] = v[i]/w[i].<br />

Sort the items in decreasing order of their vp[i]. For simplicity renumber the elements<br />

so that the first item is the one with the largerst vp and so on.<br />

The choice that the thief has to make is which item to include in the knapsack. Being<br />

a thief it is very tempting to be greedy, and go for the big buck first. Here is the<br />

algorithm:<br />

FR-Knapsack(i, w)<br />

//returns the maximum value obtainable when filling a<br />

//knapsack of capacity $w$ with using items $i$ through $n$.<br />

IF i > n RETURN 0<br />

IF w[i] S, and<br />

therefore we get a contradiction. Thus we have proven that the first item is always<br />

part of an optimal solution.<br />

The rest of the correctness proof follows by induction on i. The algorithm is trivially<br />

true when i = n. Let S1n be the optimal solution FR-KNAPSACK(1, w) and let S2n<br />

5


e the optimal solution for FR-KNAPSACK(2, w-w[1]). By induction hypothesis<br />

we assume that S2n is computed correctly by FR-KNAPSACK(2, w-w[1]). We<br />

know that the first item is part of S1n, and let the remaining part of S1n be called S ′ :<br />

S1n = v[1] + S ′ . S ′ contains items 2 through n and therefore S ′ is at most the optimal<br />

solution S2n: S ′ ≤ S2n.<br />

Then S ′ = S2n, otherwise we could replace S ′ with S2n in S1n and get a solution<br />

v[1] + S2n > v[1] + S ′ = S1n, contradiction. Thus v[1] + S2n is the optimal solution for<br />

FR-KNAPSACK(1, w).<br />

6


4. Suppose you are in charge of planning a party for <strong>Bowdoin</strong> <strong>College</strong>. The college has<br />

a hierarchical structure, which forms a tree rooted at President Mills. On the very<br />

last level are the faculty, grouped by department. (I have such a chart in my office, if<br />

you need to be visual). Each faculty has “underneath” all students taking a class with<br />

him/her that particular semester. Assume that every person is listed at the highest<br />

possible position in the tree and there are no double affiliations (everybody has one<br />

and only one supervisor in this hierarchy and no student is in more than one class).<br />

You have access to a secret database which ranks each faculty/staff/student with a<br />

conviviality rating (a real number, which can be negative if the person is really difficult<br />

or boring). In order to make the party fun for everybody, President Mills does not<br />

want both a faculty/staff/student and his or her immediate “supervisor” to attend.<br />

You are given a tree that describes the strucure of <strong>Bowdoin</strong> <strong>College</strong>. Each node has<br />

a (down) pointer to its left-most child, and a (right) pointer to its next sibling (if<br />

unclear read Section 10.4 in CLR). Each node also holds a name and a conviviality<br />

ranking. Describe an algorithm to make up a guest list that maximizes the sum of the<br />

conviviality rankings of the guests. Analyze the running time of your algorithm.<br />

Solution: Let x be a node in the tree.<br />

Let PartyMix(x) return the optimal conviviality rating obtainable from the subtree<br />

rooted at x.<br />

We want to compute PartyMix(President Mills).<br />

Here is the recursive formulation of PartyMix(x):<br />

Let ch(x) be the list of children of x.<br />

Let grc(x) be the list of grandchildren of x.<br />

PartyMix(x) = 0 if x == NULL<br />

PartyMix(x) = max {conv(x) + <br />

y∈grc(x) P artyMix(y), <br />

z∈ch(x) P artyMix(z)}<br />

To make this approach efficient, we keep a table with T [x] storing the solution of<br />

PartyMix(x). Initially all entries in the table are set to −∞.<br />

Analysis: The table has n entries. Assume that these entries are computed in bottomup<br />

order so that we can ignore the recursion costs. An entry x is computed in<br />

O(|ch(x)|+|gr(x)|) time. Thus to compute all entries it takes <br />

x |ch(x)|+|gr(x)| time.<br />

A node can only be child to a single node, so it is counted only once in <br />

x |ch(x)|.<br />

Similarly a node can be grandchild to a single node, so it is counted only once in<br />

<br />

x |gc(x)|. Thus <br />

x |ch(x)| + |gr(x)| is O(n). Therefore the algorithm takes O(n)<br />

time.<br />

7

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!