큰 문제를 작게 나누고, 같은 문제라면 한 번씩만 풀어 문제를 효율적으로 해결하는 알고리즘 기법으로, 동적 계획법으로 불리기도 한다.
DP 알고리즘을 적용하기 위해서는 다음 2가지 조건을 만족해야 한다.
Overlapping Subproblem
Optimal Substructure
주어진 문제가 여러 개의 부분 문제(subproblem)로 쪼개질 수 있는 것을 말한다.
대표적인 예로 피보나치 수열
이 있다. 피보나치 수열은 첫째 항과 둘째 항이 1이며, 그 뒤에 모든 항이 바로 앞 두 항의 합인 수열을 말한다.
N번째 피보나치 수를 구할 때, (N - 2)번째 피보나치 수 구하기
+ (N - 1)번째 피보나치 수 구하기
로 작은 문제로 나눌 수 있다.
새로운 부분 문제의 정답을 다른 부분 문제의 정답으로부터 구할 수 있는 것을 말한다.
앞에서 언급한 피보나치 수열을 구할 때, 8번째 피보나치 수를 구하면서 구했던 4번째 피보나치 수
와 9번째 피보나치 수를 구하면서 구했던 4번째 피보나치 수
는 항상 같다.
즉 매번 4번째 피보나치 수
를 구하지 않고, 전에 구했던 값을 기억해서 사용할 수 있다.
다이나믹 프로그래밍의 접근 방법에는
Top-Down
과Bottom-Up
가 있다.
Top-Down(탑-다운)
이라고 한다.메모이제이션
은 탑다운 방식에 국한되어 사용되는 표현이다. Bottom-Up
방식으로 구현하는 것이 좋다. sys
라이브러리에 포함되어 있는 setrecursionlimit()
함수를 호출하여 재귀 제한을 완화할 수 있다.d = [0] * 100
def fibo(x):
print('f(' + str(x) + ')', end=' ')
if x == 1 or x == 2:
return 1
if d[x] != 0:
return d[x]
d[x] = fibo(x - 1) + fibo(x - 2)
return d[x]
fibo(6)
Bottom-Up(보텀업)
방식이라고 한다.DP 테이블
이라고 부른다.d = [0] * 100
d[1] = d[2] = 1
n = 99
for i in range(3, n + 1):
d[i] = d[i - 1] + d[i - 2]
print(d[n])
큰 문제를 작은 문제로 나눈다는 측면에서 분할 정복
알고리즘과 비슷하게 느껴지지만 다음과 같은 차이점이 존재한다.
이것이 코딩테스트다 with 파이썬 책
galid1님의 블로그
gillog님의 벨로그
polynomeer님의 벨로그
kimlog님 블로그
kyun2da님 블로그