[Algorithm] Dynamic Programming(동적 계획법)

Jiyoung Park·2023년 1월 2일
0

Dynamic Programming

목록 보기
1/8

Dynamic Programming

  • 표(table)을 만들어 채워가면서 답을 구하는 방법
  • “programming”의 의미 : tabular method(표 방식)
  • optimization problem을 해결하기 위해 쓰임

풀이 방법

  1. 최적해의 구조적 특징을 찾는다.
  2. 최적해의 값을 재귀적으로 정의한다.
  3. 최적해의 값을 일반적으로 상향식 방법으로 계산한다.
  4. 계산된 정보들로부터 최적해를 구성한다.

Examples

Dynamic Programming 문제는 3가지 유형으로 나뉜다.
1. rod cutting
2. matrix-chain multiplication
3. longest common subsequence

1. rod cutting

11052번: 카드 구매하기

nn인치 막대를 잘라서 판매하여 얻을 수 있는 최대 수익 rnr_n을 찾아라.

length ii12345678910
price pip_i1589101717202430

rnr_nrn1,rn2,...,r1r_{n-1}, r_{n-2}, ..., r_1로부터 구할 수 있다.
rn=max1<=i<=n(pi+rni)r_n = max_{1<=i<=n}(p_i + r_{n-i})
optimal substructure를 가졌다.

top-down

MEMOIZED-CUT-ROD(p, n)
	let r[0..n] be a new array
	for i = 0 to n
		r[i] = -∞
	return MEMOIZED-CUT-ROD-AUX(p, n, r)

MEMOIZED-CUT-ROD-AUX(p, n, r)
	if r[n] >= 0
		return r[n]
	if n == 0
		q = 0
	else q = -∞
		for i = 1 to n
			q = max(q, p[i] + MEMOIZED-CUT-ROD-AUX(p, n-i, r))
	r[n] = q
	return q

bottom-up → function call이 없어서 top-down보다 효율적

BOTTOM-UP-CUT-ROD(p, n)
	let r[0..n] be a new array
	r[0] = 0
	for j = 1 to n
		q = -∞
		for i = 1 to j
			q = max(q, p[i] + r[j-i])
		r[j] = q
	return r[n]

시간 복잡도: O(n2)O(n^2)

2. Matrix-chain multiplication

11049번: 행렬곱셈순서

AiA_ix…xAjA_j행렬을 optimal 순서로 곱했을 때의 연산 횟수 m[i,j]m[i,j]를 구하라.

matrixA1A_1A2A_2A3A_3A4A_4A5A_5A6A_6
demension30×3535×1515×55×1010×2020×25

pkp_kAkA_k의 열의 개수 = Ak+1A_{k+1}의 행의 개수 (단, p0p_0A1A_1의 행의 개수)
따라서 AkA_k의 크기는 pk1p_{k-1}×pkp_k
m[i,j]={0if  i=j,minik<j{m[i,k]+m[k+1,j]+pi1pkpj}if  i<j.m[i,j] = \begin{cases}0& if\;i=j,\\\min_{i\le k<j}\{m[i,k]+m[k+1,j]+p_{i-1}p_kp_j\}&if\;i<j.\end{cases}
optimal substructure를 가지고 subproblem들이 overlap 되어있다.

MATRIX-CHAIN-ORDER(p)
	n = p.length - 1
	let m[1..n,1..n] be new table
	for i = 1 to n
		m[i,i] = 0 // 행렬이 1개일 때의 값 초기화
	for l = 2 to n // chain length
		for j = 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,k]
					m[i,j] = q
	return m

시간복잡도: O(n3)O(n^3)

3. Longest common subsequence (LCS)

9251번: LCS

XiX_iYjY_j의 LCS의 길이 c[i,j]c[i,j]를 구하라.

subsequence Z=<z1,z2,...,zk>Z = <z_1, z_2, ..., z_k> of sequence X=  <x1,x2,...,xm>X=\;<x_1,x_2,...,x_m>
단조 증가하는 X의 index sequence <i1,i2,...,ik><i_1,i_2,...,i_k>
ex) X = <A, B, C, B, D, A, B>, Z = <B, C, D, B> ⇒ <2, 3, 5, 7>

c[i,j]={0if  i=0  or  j=0,c[i1,j1]+1if  i,j>0  and  xi=yj,max(c[i1,j],c[i,j1])if  i,j>0  and  xiyj.c[i,j] = \begin{cases}0&if\;i=0\;or\;j=0,\\c[i-1,j-1]+1&if\;i,j>0\;and\;x_i=y_j,\\max(c[i-1,j],c[i,j-1])&if\;i,j>0\;and\;x_i\neq y_j.\end{cases}

LCS-LENGTH(X, Y)
	m = X.length
	n = Y.length
	let c[0..m,0..n] be new table
	for i = 1 to m // 초기화
		c[i,0] = 0
	for j = 0 to n
		c[0,j] = 0
	for i = 1 to n
		for j = 1 to n
			if x_i == y_j
				c[i,j] = c[i-1,j-1]+1
			elseif c[i-1,j] >= c[i,j-1]
				c[i,j] = c[i-1,j]
			else
				c[i,j] = c[i,j-1]
	return c

시간복잡도: O(mn)O(mn)

1개의 댓글

comment-user-thumbnail
2024년 3월 28일

통나무 대신 빵 잘라주세요

답글 달기