chap08alg

21
CHAPTER 8 Dynamic Programming

Upload: munkhchimeg

Post on 10-Jun-2015

264 views

Category:

Entertainment & Humor


0 download

TRANSCRIPT

Page 1: Chap08alg

CHAPTER 8

Dynamic Programming

Page 2: Chap08alg

Algorithm 8.1.1 Computing the Fibonacci Numbers, Version 1This dynamic-programming algorithm computes the Fibonacci number f[n]. It uses the formulas

f[1] = 1; f[2] = 1; f[n] = f[n - 1] + f[n - 2], n ≥ 3.At the conclusion of the algorithm, the array f holds the first n Fibonaccinumbers.

Input Parameters: nOutput Parameters: Nonefibonacci1(n) { // f is a local array f[1] = 1 f[2] = 1 for i = 3 to n f[i] = f[i - 1] + f[i - 2] return f[n]}

Page 3: Chap08alg

Algorithm 8.1.1 Computing the Fibonacci Numbers, Version 2This dynamic-programming algorithm computes the Fibonacci number fn . It uses the formulas f1 = 1; f2 = 1; fn = fn - 1 + fn - 2, n ≥ 3. It saves the two preceding Fibonacci numbers in the variables f_twoback and f_oneback in order to compute the next Fibonacci number.

Input Parameters: nOutput Parameters: Nonefibonacci2(n) {

if (n == 1 || n == 2)return 1

f_twoback = 1 f_oneback = 1 for i = 3 to n { f = f_twoback + f_oneback f_twoback = f_oneback f_oneback = f } return f}

Page 4: Chap08alg

Computing the Fibonacci Numbers RecursivelyThis algorithm computes the Fibonacci number fn recursively using the formulas f1 = 1; f2 = 1; fn = fn - 1 + fn - 2, n ≥ 3.

Input Parameters: nOutput Parameters: Nonefibonacci_recurs(n) { if (n == 1) return 1 if (n == 2) return 1 return fibonacci_recurs(n - 2) + fibonacci_recurs(n - 1)}

Page 5: Chap08alg

Computing the Fibonacci Numbers with MemoizationThis algorithm computes the Fibonacci number fn recursively (with memoization) using the formulas f1 = 1; f2 = 1; fn = fn - 1 + fn - 2, n ≥ 3.

Page 6: Chap08alg

Input Parameters: nOutput Parameters: Nonememoized_fibonacci(n) { for i = 1 to n results[i] = -1 // -1 means undefined return memoized_fibonacci_recurs(results,n)}

memoized_fibonacci_recurs(results,n) { if (results[n] != -1) return results[n] if (n == 1) val = 1 else if (n == 2) val = 1 else { val = memoized_fibonacci_recurs(results,n - 2) val = val + memoized_fibonacci_recurs(results,n - 1) } results[n] = val return val}

Page 7: Chap08alg

Algorithm 8.2.1 Coin Changing Using Dynamic Programming, Version 1This dynamic-programming algorithm computes the minimum number of coins to make change for a given amount. The input is an array denom that specifies the denominations of the coins, denom[1] > denom[2] > ··· > denom[n] = 1,and an amount A. The output is an array C whose value, C[i][j], is theminimum number of coins to make change for the amount j, using coins ithrough n, 1 ≤ i ≤ n, 0 ≤ j ≤ A.

Page 8: Chap08alg

Input Parameters: denoma,AOutput Parameters: Nonedynamic_coin_change1(denom,A,C) { n = denom.last for j = 0 to A C[n][j] = j for i = n - 1 downto 1 for j = 0 to A if (denom[i] > j ||

C[i + 1][j] < 1 + C[i][j - denom[i]]) C[i][j] = C[i + 1][j] else C[i][j] = 1 + C[i][j - denom[i]]}

Page 9: Chap08alg

Algorithm 8.2.2 Coin Changing Using Dynamic Programming, Version 2This dynamic-programming algorithm computes the minimum number of coins to make change for a given amount and tracks which coins are used. The input is an array denom that specifies the denominations of the coins, denom[1] > denom[2] > ··· > denom[n] = 1,and an amount A. The output consists of arrays C and used. The value, C[i][j], is the minimum number of coins to make change for the amount j, using coins I through n, 1 ≤ i ≤ n, 0 ≤ j ≤ A. The value, used[i][j], is true or false to signify whether coin i appears in the smallest set of coins computed by Algorithm 8.2.1 for the amount j using only coins i through n. The values of i and j satisfy 1 ≤ i ≤ n, 0 ≤ j ≤ A.

Page 10: Chap08alg

Input Parameters: denom,AOutput Parameters: C,useddynamic_coin_change2(denom,A,C,used) { n = denom.last for j = 0 to A { C[n][j] = j used[n][j] = true }

for i = n - 1 downto 1 for j = 0 to A if (denom[i] > j ||

C[i + 1][j] < 1 + C[i][j - denom[i]]) C[i][j] = C[i + 1][j] used[i][j] = false else C[i][j] = 1 + C[i][j - denom[i]] used[i][j] = true

}}

Page 11: Chap08alg

Algorithm 8.2.4 Computing a Minimum-Size Set of Coins for a Given AmountThis algorithm outputs a minimum-size set of coins to make change for an amount j using any of coins i through n with denominations specified by Algorithm 8.2.2. The algorithm inputs the index i, the amount j, the array denom of Algorithm 8.2.2, and the array used computed by Algorithm 8.2.2.

Page 12: Chap08alg

Input Parameters: i,j,denom,usedOutput Parameters: Noneoptimal_coins_set(i,j,denom,used) { if (j == 0) return

if (used[i][j]) { println(“Use a coin of denomination ” + denom[i]) optimal_coins_set(i,j - denom[i],denom,used) } else optimal_coins_set(i + 1,j,denom,used)}

Page 13: Chap08alg

Algorithm 8.3.1 Optimal Matrix MultiplicationThis algorithm computes the minimum number of scalar multiplications to multiply a sequence of n matrices. The input is the array size that contains the sizes of the matrices to be multiplied. The first matrix is size[0] × size[1]; the second is size[1] × size[2]; and so on. The nth matrix is size[n - 1] × size[n]. The output is the array s whose value, s[i][j], is the minimum number of scalar multiplications to multiply matrices i through j. The value ∞ is the largest available integer value.

Page 14: Chap08alg

Input Parameters: sizeOutput Parameters: sopt_matrix_mult(size,s) { n = size.last for i = 1 to n s[i][i] = 0 // w = j - i for w = 1 to n - 1 for i = 1 to n - w { j = w + i s[i][j] = ∞ for k = i to j - 1 { q = s[i][k] + s[k + 1][j] +

size[i - 1] * size[k] * size[j] if (q < s[i][j]) s[i][j] = q } }}

Page 15: Chap08alg

Algorithm 8.4.2 Computing the Length of a Longest Common SubsequenceThis dynamic-programming algorithm computes the length c[i][j] of a longest common subsequence of a[1], ... , a[i] and b[1], ... , b[j] for i = 0, ... , m and j = 0, ... , n.

Input Parameters: a,bOutput Parameters: cLCS(a,b,c) {

m = a.lastn = b.lastfor i = 0 to m

c[i][0] = 0for j = 1 to n

c[0][j] = 0for i = 1 to m

for j = 1 to nif (a[i] != b[j])

c[i][j] = max(c[i - 1][j],c[i][j - 1])else

c[i][j] = 1 + c[i - 1][j - 1]}

Page 16: Chap08alg

Algorithm 8.4.3 Computing a Longest Common SubsequenceThis algorithm uses the array c computed by Algorithm 8.4.2 to output a longest common subsequence. The array a of length m is the first sequence input to Algorithm 8.4.2, and n is the length of the second sequence input to Algorithm 8.4.2.

Input Parameters: a,m (length of a),n (length of second sequence),c (contains lengths of longest common subsequences)Output Parameters: NoneLCS_print(a,m,n,c) {

if (c[m][n] == 0) return if (c[m][n] == c[m - 1][n]) LCS_print(a,m - 1,n,c) else if (c[m][n] == c[m][n - 1]) LCS_print(a,m,n - 1,c) else { LCS_print(a,m - 1,n - 1,c) print(a[m]) }}

Page 17: Chap08alg

Algorithm 8.5.3 Floyd’s Algorithm, Version 1This algorithm computes the length of a shortest path between each pair of vertices in a simple, undirected, weighted graph G. All weights are nonnegative. The input is the adjacency matrix A of G. The output is the matrix A whose ijth entry is the length of a shortest path from vertex i to vertex j.

Input Parameter: AOutput Parameter: Aall_paths(A) { n = A.last for k = 1 to n // compute A(k) for i = 1 to n for j = 1 to n if (A[i][k] + A[k][j] < A[i][j]) A[i][j] = A[i][k] + A[k][j]}

Page 18: Chap08alg

Algorithm 8.5.4 Floyd’s Algorithm, Version 2This algorithm computes the length of a shortest path between each pair of vertices in a simple, undirected, weighted graph G and stores the vertex that follows the first vertex on each shortest path. All weights are nonnegative. The input is the adjacency matrix A of G. The output is the matrix A whose ijth entry is the length of a shortest path from vertex i to vertex j and the matrix next whose ijth entry is the vertex that follows i on a shortest path from i to j.

Page 19: Chap08alg

Input Parameter: AOutput Parameter: A,nextall_paths(A,next) {

n = A.last// initialize next: if no intermediate// vertices are allowed next[i][j] = jfor i = 1 to n

for j = 1 to nnext[i][j] = j

for k = 1 to n // compute A(k) for i = 1 to n for j = 1 to n if (A[i][k] + A[k][j] < A[i][j]) { A[i][j] = A[i][k] + A[k][j]

next[i][j] = next[i][k]

}}

Page 20: Chap08alg

Algorithm 8.5.5 Finding a Shortest PathThis algorithm outputs a shortest path from vertex i to vertex j in a simple, undirected, weighted graph G. It assumes that matrix next has already been computed by Algorithm 8.5.4.

Input Parameters: next,i,jOutput Parameters: Noneprint_path(next,i,j) { // if no intermediate vertices, just

// print i and j and return if (j == next[i][j]) { print(i + “ ” + j) return } // output i and then the path from the vertex // after i (next[i][j]) to j print(i + “ ”) print_path(next,next[i][j],j)}

Page 21: Chap08alg

Algorithm 8.5.12 Warshall’s Algorithm

This algorithm computes the transitive closure of a relation R on {1, ... , n}. The input is the matrix A of R. The output is the matrix A of the transitive closure of R.

Input Parameters: AOutput Parameters: Atransitive_closure(A) {

n = A.lastfor k = 1 to n

for i = 1 to n for j = 1 to n

A[i][j] = A[i][j] (A[i][k] A[k][j])}