Download Document

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Non-negative matrix factorization wikipedia , lookup

Gaussian elimination wikipedia , lookup

Matrix multiplication wikipedia , lookup

Transcript
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.
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]
}
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
}
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)
}
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.
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
}
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.
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]]
}
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.
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
}
}
Algorithm 8.2.4 Computing a MinimumSize 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.
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)
}
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.
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
}
}
}
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]
}
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])
}
}
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]
}
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.
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]
}
}
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)
}
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])
}