✨나동빈님의 다이나믹 프로그래밍 강의를 보고 작성한 글입니다.
https://www.youtube.com/watch?v=5Lu34WIx2Us
다이나믹 프로그래밍은 메모리를 적절히 사용해서 수행 시간 효율성을 향상 시키는 방법이다.
일반적인 프로그래밍 분야에서 쓰이는 동적과 쓰이는 의미가 조금 다르다.
이미 계산된 결과는 별도의 메모리 영역에 저장해서 다시 계산하지 않도록 한다.
ex) 피보나치 수열
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
An = An-1 + An-2 ( a1=1, a2=1 )
앞에 있는 두 수의 합이 현재의 값으로 표현된다.
➣ 중복 부분 문제 조건을 보아 우리는 이미 해결해 놓은 문제를 다른 메모리 공간에 기록해놔야 한다
는 사실을 알 수 있다.
( 기록하지 않으면 매우 비효율적으로 계속 계산을 해야하기 때문~ )
한번 계산한 결과를 메모리 공간에 메모하는 기법이다.
O(N)
이다.#메모이제이션을 위한 리스트 초기화
d = [0] * 100
#top-down 방식
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]
print(fibo(99))
top-down 방식은 하향식으로, 큰 문제를 해결하기 위해 작은 문제들을 재귀적으로 호출한다.
그 작은 문제들이 해결되었을 때 큰 문제를 해결할 수 있도록 한다.
그 과정에서 한번 해결한 문제는 메모해두어서 그대로 가져오도록 한다. (메모이제이션)
bottom-up 방식은 상향식으로, 작은 문제들을 하나씩 해결해나가면서 그 다음 문제를 해결해나가는 방식이다. 보통 반복문을 이용한다.
#메모이제이션을 위한 리스트 초기화
d = [0] * 100
#bottom-up 방식
d[1]=1
d[2]=1
n = 99
for i in range(3, n+1):
d[i] = d[i-1] + d[i-2]
print(d[n])
다이나믹 프로그래밍과 분할정복은 모두 최적 부분 구조를 가질 때 사용할 수 있다.
➣ 큰 문제를 작은 문제로 나눌 수 있고 작은 문제의 답을 모아서 큰 문제를 해결할 수 있기때문이다.
두 방법의 차이점은 부분 문제의 중복이다.
⭐️ 다이나믹 프로그래밍만 각 부분의 문제들이 서로 영향을 미치면 부분 문제가 중복된다.