1 / 21

CHAPTER 8

CHAPTER 8. Dynamic Programming. Algorithm 8.1.1 Computing the Fibonacci Numbers, Version 1. This 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.

salaam
Download Presentation

CHAPTER 8

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CHAPTER 8 Dynamic Programming

  2. Algorithm 8.1.1 Computing the Fibonacci Numbers, Version 1 This 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 Fibonacci numbers. Input Parameters: n Output Parameters: None fibonacci1(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] }

  3. Algorithm 8.1.1 Computing the Fibonacci Numbers, Version 2 This 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: n Output Parameters: None fibonacci2(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 }

  4. Computing the Fibonacci Numbers Recursively This algorithm computes the Fibonacci number fn recursively using the formulas f1 = 1; f2 = 1; fn = fn - 1 + fn - 2, n≥ 3. Input Parameters: n Output Parameters: None fibonacci_recurs(n) { if (n == 1) return 1 if (n == 2) return 1 return fibonacci_recurs(n - 2) + fibonacci_recurs(n - 1) }

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

  6. Input Parameters: n Output Parameters: None memoized_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 }

  7. Algorithm 8.2.1 Coin Changing Using Dynamic Programming, Version 1 This 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 the minimum number of coins to make change for the amount j, using coins i through n, 1 ≤ i ≤ n, 0 ≤ j ≤ A.

  8. Input Parameters: denoma,A Output Parameters: None dynamic_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]] }

  9. Algorithm 8.2.2 Coin Changing Using Dynamic Programming, Version 2 This 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.

  10. Input Parameters: denom,A Output Parameters: C,used dynamic_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 } }

  11. Algorithm 8.2.4 Computing a Minimum-Size Set of Coins for a Given Amount This 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.

  12. Input Parameters: i,j,denom,used Output Parameters: None optimal_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) }

  13. Algorithm 8.3.1 Optimal Matrix Multiplication This 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.

  14. Input Parameters: size Output Parameters: s opt_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 } } }

  15. Algorithm 8.4.2 Computing the Length of a Longest Common Subsequence This 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,b Output Parameters: c LCS(a,b,c) { m = a.last n = b.last for i = 0 to m c[i][0] = 0 for j = 1 to n c[0][j] = 0 for i = 1 to m for j = 1 to n if (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] }

  16. Algorithm 8.4.3 Computing a Longest Common Subsequence This 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: None LCS_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]) } }

  17. Algorithm 8.5.3 Floyd’s Algorithm, Version 1 This 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: A Output Parameter: A all_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] }

  18. Algorithm 8.5.4 Floyd’s Algorithm, Version 2 This 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.

  19. Input Parameter: A Output Parameter: A,next all_paths(A,next) { n = A.last // initialize next: if no intermediate // vertices are allowed next[i][j] = j for i = 1 to n for j = 1 to n next[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] } }

  20. Algorithm 8.5.5 Finding a Shortest Path This 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,j Output Parameters: None print_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) }

  21. 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: A Output Parameters: A transitive_closure(A) { n = A.last for 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]) }

More Related