Dynamic Programming은 Optimization Problem을 해결하는 전략 중 하나
다이나믹 프로그래밍의 구현은 일반적으로 Top-Down (하향식), Bottom-Up (상향식) 으로 구성된다.
Top-Down | Bottom-Up | |
---|---|---|
구조 | recursive(재귀) | iterative(반복문) |
subproblem 결과 저장 | memoization | tabulation |
주로 사용되는 문제 | sub problem 일부만 계산해도 최종 최적의 해를 구할 수 있을 때 | 모든 sub problem 을 계산해야 최종 최적의 해를 구할 수 있을 때 |
DP의 Top-Down 방식은 재귀함수에 메모이제이션 기법이 적용된 방법
DP의 Bottom-Up 방식은 가장 작은 문제부터 답을 찾아 가면서 전체 문제의 답을 구하는 방식이다.
보통 반복문으로 구현한다. 재귀 호출을 하지 않으므로 시간과 메모리 사용량이 상대적으로 적다.
정상을 오르는 데 n번의 스텝이 필요한 계단이 있다. 한 번에 한 스텝 혹은 두 스텝을 오를 수 있을 때, 정상까지 오르기 위해 몇 개의 유니크한 방법이 있는지 구하시오.
총 몇 개의 유니크한 방법 = 최대 몇 개의 유니크한 방법이 있는지
정상에 오르기 직전에는 어느 위치에 있을까?
n은 n-1 위치거나 n-2 위치 일 것이다.
그렇다면 n 은 n-1 에 도달하기 위한 방법의 수 + n - 2 에 도달하기 위한 방법의 수
f(n) = f(n-1) + f(n-2)
재귀
public int climb(int n){
if (n <= 2) return n;
return climb(n-1) + climb(n-2);
}
위 그림을 보면 겹치는 Sub Problem이 많기 때문에 결과를 메모해두고 재사용한다.
Top-Down
int memo = {}
public int climb(int n){
if (memo[n] != 0) return dp[n];
if (n <= 2) return n;
dp[n] = climb(n - 1) + climb(n - 2);
return dp[n];
}
Bottom-Up
int[] dp = new int[n];
dp[1] = 1;
dp[2] = 2;
public int climb(int n){
for(int i = 3; i < n; i++){
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}