큰 문제를 작은 문제로 쪼개어 작은 문제들을 해결, 저장 하여 큰 문제를 해결한다.
즉, 한번 푼 문제는 다시 풀지 않음
-> 메모이제이션(memoization) : 계산한 결과는 배열에 저장.
greedy가 작동하지 않는 상황이면 일반적으로 DP가 올바른 방법
반복 | 재귀 |
---|---|
일반적으로 서로 내포된 몇개의 for 루프를 작성 | 순진한 솔루션이나 역추적 구현, 다음 메모제이션 추가 -> 쉬움 |
속도 | 쉬운 접근 |
오버헤드 작-> 실행시간 작 | 단일 문제에서 방문할 스테이트 수가 더 적음 |
쉬운 복잡도 | 상태의 순서 중요하지 않음 |
어려운 기술 구현가능 |
1) 동일한 작은 문제들이 반복하여 나타나는 경우에 사용한다. ( = 큰 문제를 중복되는 작은 문제로 쪼갤 수 있다.)
2) 작은 문제에서 구한 결과로 그것을 포함하는 큰 문제에서 활용하여 전체 결과를 낼 수 있다.
! 분할 정복과 DP는 큰 문제를 작게 쪼갠 문제들을 해결하고 연계적으로 큰 문제를 해결하는 것은 같음. 하지만 분할 정복은 쪼개진 작은 문제가 반복이 아닐때 사용하므로 DP와의 차이점을 가짐.
1) DP문제인지 확인
2) 문제의 변수 파악
3) 변수 간 관계식 만들기(점화식)
4) memoization
5) 초기값 확인하기(기저 상태 파악)
6) 구현
ex) 피보나치 수열
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144 ...
==> 재귀 (피보나치 수열 점화식) return f(n) = f(n-1) + f(n-2)
위 그림처럼 똑같은 값을 또 계산하여 연산이 기하급수적으로 늘어남. -> 비효율
==> DP사용
🔷프로그래머스 피보나치 수 문제
🔷하노이의 탑
이전 값(작은 문제의 결과)를 이용하여 큰 문제의 값을 도출
def solution(n):
li = [0,1]
for i in range(n-1):
answer = li[0] + li[1]
if i%2 == 0 : li[0] = answer
else : li[1] = answer
return answer % 1234567