hw7
hw7
Problem Set 7
Lecturer: Yevgeniy Dodis Due: 4 pm on Tuesday, April 1
In class, we gave a dynamic programming solution where we recursed on the last piece of the
rod. In this problem, you will give an alternative dynamic programming solution, where we instead
recurse on the largest piece.
In particular, define T [n, m] to be the maximum price you can get when selling a rod of length
n where the largest piece is of length at most m. Formally,
`
X
T [n, m] = max P [ij ].
i1 +···+i` =n
max(i1 ,...,i` )≤m j=1
(a) (2 points) Assume that the optimal rod-cutting has a largest rod of size m∗ ≤ m. Give a
formula for T [n, m] in terms of one value of T [·, ·] and P [·].
(b) (4 points) Write a recurrence for T [n, m] in terms of T [i, j] and P [·] for i < n, j ≤ m. Do
not forget the base case!
(c) (4 points) Write an algorithm RodCutTwo that solves the rod-cutting problem in a bottom-
up manner. To this end, complete the following skeleton.
RodCutTwo(n, P )
Initialize an n × n array T
for i = 1 to n do
. . . . . . . . . . . . //initialize the base case
for i = 1 to n do
for j = 1 to . . . do
max = 0
for k = 1 to j do
max = max (max, . . . . . . . . . . . . )
return . . . . . . . . .
PS 7, Page 1
(d) (1 point) What is the runtime of RodCutTwo? How does this compare to the algorithm
from lecture? Justify your answer.
(e) (2 points) Write a recursive algorithm RodCutMemo which solves the rod-cutting algorithm
efficiently using memoization.
(f) (2 points) How does the runtime of RodCutMemo compare to the algorithm from part (c)?
(g) (Extra Credit)(5 points) Prove that the asymptotic runtime of RodCutMemo is the same
as the asymptotic runtime of RodCutTwo. Warning: this is very hard. (Hint: To prove
a lower bound on the runtime, find a large set of different (a, b) such that computing T [n, n]
requires computing T [a, b]. In particular, consider values of T [a, b] which can be reached after
two recursions.)
(a) (5 points) Consider sorting the n words in the dictionary by their length. Let words be the
sorted array such that all words of length 1 come first, then words of length 2 and so on.
We define the array C as follows: C[i] is the length of the longest word chain ending with
words[i].
Show how to compute each C[i] in time k 2 n.
(b) (5 points) Show how to compute each C[i] in k 2 log n. (Hint: Think of sorting each group of
words of the same length in some useful order.)
(c) (2 points) What is the running time of the procedure that computes C and uses it to determine
the length of the longest word chain?
(a) (4 points) Without designing any new dynamic programming algorithms, show how to solve
the problem in time O(n log n) plus the time to solve the longest common subsequence problem
studied in class.
PS 7, Page 2
(b) (4 points) While part (a) already gives us O(n2 ) solution, here we will design a more direct
O(n2 ) dynamic programming algorithm for a related problem. Let p[i] denote the length of
the largest increasing subsequence among a1 . . . ai which contains ai as its last element. Write
a recursive formula for the p[i] using p[j] for j < i, and show how to compute all p[i]’s by
dynamic programming in time O(n2 ).
(c) (2 points) Assuming you solved part (b), use the values p[1], . . . , p[n] to design an explicit
O(n2 ) algorithm for the original problem (i.e., longest increasing subsequence without any
restrictions on the last element).
(d) (Extra Credit)(5 points) Here we will design a more clever algorithm running in time
O(n log n) total. We will maintain two arrays M [j] and [i], where
• M [j] contains the smallest possible largest element ak of all increasing subsequences of
length j seen so far (as we scan A). E.g., in our example A = (10, 11, 12, 1, 8, 2, 7, 3, 4, 4)
above, M [3] is initially infinity (i = 0), then becomes 12 when i = 3 is processed, then
becomes 7 when i = 7, then becomes 3 when i = 8, and stays at 3 till the end.
• L[i] contains the pointer to the index k of the predecessor of ai in the longest increasing
subsequence ending in ai ([i] = 0 if no such predecessor). E.g., in our example, [3] = 2
(since a2 = 10 is predecessor of a3 = 11 in 10, 11, 12) and [9] = 8 (since a8 = 3 is
predecessor of a9 = 4 in 1, 2, 3, 4).
In our example A = (10, 11, 12, 1, 8, 2, 7, 3, 4, 4), this is how these arrays look like as we scan
over the original array A:
... and so on until at i = 10 you get some “useful” values (e.g., M [4] = 4, M [5] = ∞, and
[9] = 8, for example).
First, finish the sample evolution of M and L above which I stopped at i = 5.
Then, returning to the general problem, show how you can maintain the two arrays in time
O(log n) per index 1 ≤ i ≤ n, and then how this allows you to solve the original problem in
total time O(n log n).
PS 7, Page 3