본문 바로가기
Problem Solving/알고리즘

동적 계획법

by 사향낭 2022. 1. 7.

Dynamic Programming (DP)

 

 

Divde & Conquer 과 같이 문제를 작은 부분문제들로 쪼개는 과정을 거친다.

 

하지만 DP는 memoization을 사용한다는 차이점이 있다.

 

여기서 memoization이란 한 번 계산한 값을 저장해 두었다 재활용하는 기법을 의미한다.

 

 

종합하자면, Divide & Conquer은 부분 문제들이 서로 겹치지 않을 때 사용하기 좋다.

 

만약 동일한 부분 문제들이 계산 과정에서 여러 번 등장한다면, 중복 계산을 피하는 DP를 사용하는 것이 좋다.

 

 

이항 계수 (binomial coefficient) 계산을 예로 들어보자.

 

$$ \binom{4}{2} = \binom{3}{1} + \binom{3}{2} = (\binom{2}{0} + \binom{2}{1}) + (\binom{2}{1} + \binom{2}{2}) $$

 

계산이 중복되는 모습을 확인할 수 있다.

 

# Without memoization

int binom(int n, int k) {
	if (k == 0 || n == k) {
    	return 1;
    }
    
    return binom(n - 1, k - 1) + binom(n - 1, k);
}

 

 

# With memoization

vector<vector<int> > dp(100, vector<int>(100, -1);

int binom(int n, int k) {
	if (dp[n][k] != -1) {
    	return dp[n][k];
    }

	if (k == 0 || n == k) {
    	return dp[n][k] = 1;
    }
    
    return dp[n][k] = (binom(n - 1, k - 1) + binom(n - 1, k));
}

 

가능하지 않은 값으로 초기화해준 cache를 만들어 주고 사용을 할 때 초기화 해준 값이 변경되어있다면 바로 가져와서 쓰고 그대로라면 계산해서 넣어준다.

 

 

메모리를 희생하고 시간을 버는거지만, 공정한 trade off라기엔 효용이 너무 좋아진다.

 

 

대표격인 문제로는

 

 

10870번: 피보나치 수 5

피보나치 수는 0과 1로 시작한다. 0번째 피보나치 수는 0이고, 1번째 피보나치 수는 1이다. 그 다음 2번째 부터는 바로 앞 두 피보나치 수의 합이 된다. 이를 식으로 써보면 Fn = Fn-1 + Fn-2 (n ≥ 2)가

www.acmicpc.net

 

 

11726번: 2×n 타일링

2×n 크기의 직사각형을 1×2, 2×1 타일로 채우는 방법의 수를 구하는 프로그램을 작성하시오. 아래 그림은 2×5 크기의 직사각형을 채운 한 가지 방법의 예이다.

www.acmicpc.net

 

 

 

11055번: 가장 큰 증가 부분 수열

수열 A가 주어졌을 때, 그 수열의 증가 부분 수열 중에서 합이 가장 큰 것을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {1, 100, 2, 50, 60, 3, 5, 6, 7, 8} 인 경우에 합이 가장 큰 증가 부분 수

www.acmicpc.net

 

'Problem Solving > 알고리즘' 카테고리의 다른 글

0 - 1 BFS  (0) 2022.03.22
Prefix function, Knuth-Morris-Pratt algorithm  (0) 2022.01.17
Following materials  (0) 2022.01.17
분할 정복  (0) 2022.01.07
무식하게 풀기  (0) 2022.01.06

댓글