
📢 분할 정복과 같은 접근 방식을 보이지만, 계산 결과를 재활용 하는 특징을 가진 알고리즘
이를 적용해서 문제를 풀기 위해서는 아래 2가지 조건을 만족해야해요.
📢 2번 이상 호출되는 부분 문제
위의 의미에서 설명했듯이, 특정 부분 문제는 2번 이상 문제를 푸는 과정 을 가질 수 있어요. 이를 Overlapping Subproblems라고 말해요. Overlapping Subproblems는 불필요한 시간 낭비로 이어지기 때문에, Dynamic Programming을 통해 해결할 수 있어요.
📢 각 부분 문제의 최적해만 있다면 전체 문제의 최적해를 쉽게 얻어낼 수 있다
예를 들어 위의 그림에서 울산에서 대구까지 가는 가장 짧은 길을 찾는 문제를 풀려고 해요. 이때, 반드시 경주를 거쳐서 가야한다고 하면, 우리는 (울산 -> 경주) (경주 -> 대구) 각각의 가장 짧은 경로를 찾아 이를 연결하기만 한다면 (울산 -> 대구) 전체 경로에서 가장 짧은 경로를 찾을 수 있게 돼요.
대개 2가지의 구현 방법이 있다고 알려져 있어요.
📢 작을 문제를 호출해서 큰 문제를 해결하는 방법
- 재귀 호출을 이용해서 문제를 해결하는 방법
- Memoization(메모이제이션)을 활용
// memo는 -1로 초기화가 되어있다는 가정
int fibonacchi(int num, vector<int> memo) {
// memo[num]이 -1이라는 것은 처음 부분 문제를 해결한다는 의미
if(memo[num] == -1) {
int result;
if(num == 0 || num == 1)
result = n;
else
// 함수의 재귀 호출을 사용
result = fibonacchi(n - 1, memo) + fibonacchi(n - 2, memo);
memo[n] = result;
}
// -1이 아니라는 것은 이미 문제를 한 번 풀었다는 의미이므로 memeo 값 사용
return memo[n];
}
📢 작은 문제부터 하나씩 해결해 큰 문제를 해결하는 방법
- 반복문을 이용하여 문제를 해결하는 방법
- Table을 활용
int fibonacchi(int num) {
// table을 미리 선언
vector<int> table(num + 1, 0);
table[0] = 0, table[1] = 1;
for(int i = 2; i <= n; i++)
// table 값을 이용하여 해결
// 가장 작은 문제를 해결하면서 큰 문제를 해결해나간다
table[i] = table[i - 1] + table[i - 2];
return table[n];
}
백준 2839 - 설탕 배달
백준 2839 - 해답
백준 9251 - LCS
백준 9251 - 해답