복잡한 문제를 더 작은 하위 문제로 나누어 해결하는 알고리즘 설계 기법
: stations, : assembly time in the ith station, Entry time: e, Exit time: x, Transfer time:
가장 빠른 assembly time을 찾자
빨간색의 숫자는 line 1으로부터 온 것, 파란색의 숫자는 line 2로부터 온 것이다.
배열 S는 까지의 fastest way를 기록해놓은 것이다. (: line number, : station number)해당 station에서 fastest way의 이전 단계가 어느 line이였는지를 알려주는 배열 L을 사용한다.
마지막 직전의 station의 line을 알려준다.
FASTEST-WAY (a, t, e, x, n)
s[1][1] = e[1] + a[1][1]
s[2][1] = e[2] + a[2][1]
for j= 2 to n
if s[1][j−1] ≤ s[2][j−1] + t[2][j−1]
s[1][j] = s[1][j−1] + a[1][j]
l[1][j] = 1
else
s[1][j] = s[2][j−1] +t[2][j−1] + a[1][j]
l[1][j] = 2
if s[2][j−1] ≤ s[1][j−1] + t[1][j−1]
s[2][j] = s[2][j−1] + a[2][j]
l[2][j] = 2
else s[2][j] = s[1][j−1] + t[1][j−1] + a[2][j]13l[2][j] = 1
if s[1][n] + x[1] ≤ s[2][n] + x[2]
s* = s[1][n] + x[1]
l* = 1
else s* = s[2][n] + x[2]
l* = 2
a[i][j]: time for
t[i][j]: transfer time from or
e[i]: entry time
x[i]: exit time
PRINT-STATIONS (l, l*, n)
i = l*
print "line " i", station" n
for j = n downto 2
i = l[i][j]
print "line " i", station" j − 1
Running time:
space consumption
n 길이의 Rod(막대)가 주어졌을 때, 가장 이익이 많이 남도록 막대를 나누는 방법을 구하는 문제
를 i 길이일 때, 최대 이익이라고 할 때, 를 이용하면 각 길이에 대한 를 구할 수 있다.
두 조각으로 나눌 때, 사용한 i를 저장할 배열 S를 이용하여 구현할 수 있다.
EXTENDED-BOTTOM-UP-CUT-ROD (p, n)
let r[0 .. n] and s[0 .. n] be new arrays
r[0] = 0
for j = 1 to n
q= −∞
for i = 1 to j
if q < p[i] + r[j − i]
q = p[i] + r[j − i]
s[j] = i
r[j] = q
return r and s
r[i] = i 길이의 최대 이익
s[i] = i 길이에서, 세분화한 부분의 길이
PRINT-CUT-ROD-SOLUTION(p, n)
(r, s) = EXTENDED-BOTTOM-UP-CUT-ROD (p, n)
while n > 0
print s[n]
n = n – s[n]
두 문자열아 주어졌을 때, 가장 긴 common subseqeunce를 구하는 문제
X의 길이를 m, Y의 길이를 n이라고 할 때, 는 X, Y의 한 문자라고 하자
c[i][j]: sequences 와 에서의 LCS의 길이
화살표는 Back tracking을 위해 사용한다.
(i, j) 입장에서는 (i-1, j-1), (i-1, j), (i, j-1) 3개의 경우만 고려하면 된다.
LCS-LENGTH (X, Y)
m= X.length
n= Y.length
let b[1 .. m][1 .. n] and c[0 .. m][0 .. n] be new tables
for i = 1 to m
c[i][0] = 0
for j= 0 to n
c[0][j] = 0
for i = 1 to m
for j = 1 to n
if x_i == y_j
c[i][j] = c[i−1][j−1] +1
b[i][j] = "↖"
else if
c[i−1][j] ≥ c[i][j−1]
c[i][j] = c[i−1][j]
b[i][j] = "↑"
else
c[i][j] = c[i][j−1]
b[i][j] = "←"
return c and b
b[i][j]: Back-tracking을 위한 화살표를 저장하기 위한 배열
c[i][j]: 와 의 Longest common subsequence의 길이를 저장하는 배열
PRINT-LCS (b, X, i,j)
if i==0 or j==0
return
if b[i][j] =="↖"
PRINT-LCS (b, X, i−1, j−1)
print x_i
else if b[i][j] =="↑"
PRINT-LCS (b, X, i−1, j)
else
PRINT-LCS (b, X, i, j−1)
화살표가 "↖"인 지점을 잘 살펴야한다.
2개 이상의 LCS가 존재하는 경우

A (p x q) 와 B (r x s) 행렬이 있을 때, q = r 이어야 두 행렬을 곱할 수 있고, 필요한 공간은 pr이며, scalar multiplication의 횟수는 pqr이다.
계산 순서에 따라 계산 결과는 동일하지만, 계산 횟수는 바뀔 수 있다.
의 n개의 행렬이 주어졌을 때, 행렬은 x 의 차원을 가졌다고 가정하자.
scalar multiplication의 횟수를 최소화하는 계산 순서를 찾는 문제이다.
p(n)을 n개의 행렬의 곱에 대한 괄호의 개수라고 하자.
괄호의 개수는 이다.
m[i][j]: 를 계산하는 scalar multiplication의 최소 횟수
s[i][j]: m[i][j]를 최소화하는 k를 저장
: 를 계산하는데 소요되는 계산 횟수
p[i]: 의 행 개수를 저장

MATRIX-CHAIN-ORDER (p)
n = p.length−1
let m[1 .. n][1 .. n] and s[1 .. n−1][2 .. n] be new tables
for i = 1 to n
m[i][i] = 0 //initialize diagnal element to 0
for l = 2 to n // l is the chain length
for i = 1 to n − l + 1
j= i + l − 1
m[i][j] = ∞
for k = i to j − 1
q = m[i][k] + m[k+1][j] + p[i−1]p[k]p[j]
if q < m[i][j]
m[i][j] = q
s[i][j] = k
return m and s
PRINT-OPTIMAL-PARENS (s,i,j)
if i == j
print "A_i"
else print "("
PRINT-OPTIMAL-PARENS(s, i, s[i][j])
PRINT-OPTIMAL-PARENS(s, s[i][j] +1, j)
print ")"
s[i][j] = k의 값
