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 f n . It uses the formulas f 1 = 1; f 2 = 1; f n = f n - 1 + f n - 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 f n recursively using the formulas f 1 = 1; f 2 = 1; f n = f n - 1 + f n - 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 f n recursively (with memoization) using the formulas f 1 = 1; f 2 = 1; f n = f n - 1 + f n - 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 n th 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 ij th 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 ij th entry is the length of a shortest path from vertex i to vertex j and the matrix next whose ij th 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 ]) }