https://school.programmers.co.kr/learn/courses/30/lessons/12945
하나의 큰 문제를 여러 개의 작은 문제로 나누고, 그 결과를 저장해서 다시 큰 문제를 해결할때 저장한 값을 가져오는 방식으로 해결
시간 복잡도:
O(N^2) -> O(N) 으로 확연히 줄어듦. 이는 동일한 계산을 반복하지 않아도 되니까.
DP 적용 조건
- Overlapping subproblems: 부분 문제가 반복적으로 나타나야 한다.
반복적으로 나타나지 않을 경우, 재사용 불가능!- Optimal Substructure: 부분 문제의 최적 결과 값으로 전체 문제의 최적 결과를 낼 수 있어야 한다.
DP 적용 과정
1) DP 적용 조건 확인 - 2) 변수 파악 -
3) 변수 간 관계식 만들기 - 4) 메모하기(값 저장) -
5) 기저 상태 파악 - 6) 구현
구현 방법
공통점 | 주어진 문제를 작게 쪼개서 하위 문제로 해결하고 연계적으로 큰 문제를 해결 |
---|---|
차이점 | 분할정복: 분할된 하위 문제가 동일하게 중복이 일어나지 않는 경우에 사용 |
차이점 | DP: 동일하게 중복이 일어나는 경우에 사용 |
예를 들어, 피보나치 수열을 생각해보면 f(n) = f(n-1) + f(n-2)로 관계식이 도출된다.
n이 어떤 수가 되건, n-1번째 수와 n-2번째 수를 더해야 한다. n이 5라면, 4일 때와 3일 때를 구하고, 각각의 값을 또 구하기 위해 (2일 때, 3일 때) + (1일 때, 2일 때)로 반복적으로 내려가야 한다.
즉, n이 어떤 수가 되든,그 하위의 수를 구하는 부분은 중복적으로 나타난다.
따라서, 병합 정렬은 분할 정복으로, 피보나치 수열은 동적 프로그래밍(DP)로 해결이 가능하다!
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int solution(int n) {
int answer = 0;
int arr[100001];
// F(n)은 이전 2개의 state 합
arr[0] = 0;
arr[1] = 1;
for (int i = 2; i <= n; i++) {
arr[i] = (arr[i-1] + arr[i-2]) % 1234567;
}
answer = arr[n];
return answer;
}
출처:
https://ansohxxn.github.io/algorithm/dp/
https://hongjw1938.tistory.com/47