컴퓨터를 활용해도 해결하기 어려운 문제는 무엇일까? 최적의 해를 구하기에 시간이 매우 많이 필요하거나 메모리 공간이 매우 많이 필요한 문제 등이 컴퓨터로도 해결하기 어려운 문제이다. 따라서 우리는 메모리 공간을 약간 더 사용하여 연산 속도를 비약적으로 증가시키는 다이나믹 프로그래밍을 사용한다.
피보나치 수열을 예로 들어보자.
a_n+2 = a_n+1 + a_n
으로 표현할 수 있다.#소스코드
def fibo(x):
if x == 1 or x == 2:
return 1
return fibo(x - 1) + fibo(x - 2)
위의 문제는 다이나믹 프로그래밍을 사용하면 효율적으로 해결할 수 있다. 다이나믹 프로그래밍을 사용할땐느 2가지 조건이 필요하다.
- 큰 문제를 작은 문제로 나눌 수 있다.
- 작은 문제에서 구한 정답은 그것을 포함하는 큰 문제에서도 동일하다.
위에서의 연산이 많이 되는 피보나치 수열 문제를 메모이제이션 기법을 사용해서 해결해보자. 메모이제이션은 다이나믹 프로그래밍을 구현하는 방법중 한 종류로 한 번 구한 결과를 메모리에 메모해두고 같은 식을 다시 호출하면 메모한 결과를 그대로 가져오는 기법을 의미한다.
참고)
메모이제이션
은 탑다운에서 사용하는 용어이며, 보텀업 방식에서는DP 테이블
이라고 부른다.
#메모이제이션: 한번 계산된 결과를 리스트에 저장
d = [0] * 100
def fibo(x):
#종료 조건
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(99)
를 호출해도 매우 빠른 속도로 정답을 도출한다.탑다운 방식은 처음에 재귀함수를 이용해서 dp를 작성하는 방법을 의미하고, 보텀업 방식은 단순히 반복문을 이용하여 차근차근 답을 도출하는 방식이다. 결론부터 말하면 보텀업 방식을 사용하여 dp를 작성하면 된다. 왜냐하면 탑다운 방식에서는 recursion depth (재귀함수 깊이)
와 관련해서 오류가 발생할 수 있기 때문이다.
d = [0] * 100
d[1] = 1
d[2] = 2
n = 99
for i in range(3, n + 1):
d[i] = d[i - 1] + d[i - 2]
d = [0] * 100
def fibo(x):
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]