1. 동적 계획법(Dynamic Programming)이란?

분할 정복과 같은 접근방식을 갖고 있습니다. 
처음 주어진 문제를 더 작은 문제들로 나눈 뒤 각 조각의 답을 계산하고,
이 답들로부터 원래 문제에 대한 답을 계산해 내기 때문입니다. 

차이가 발생하는 부분은 문제를 나누는 방식입니다.
부분문제가 여러번 사용될 수 있을 때 여러번 중복 계산하는 것이 아닌, 
한번만 계산하고 저장해둬 재활용해 사용합니다.


 

 

 (a)서로 연관이 없는 부분문제

 (b)서로 의존하고 있는 부분문제

(a)는 서로 연관이 없어 단순히 재귀 호출을 통해 문제를 풀어도 한 부분문제를 한 번만 해결합니다.
(b)는 부분문제가 서로 의존하고 있어, 단순 재귀로 풀면 중복 계산이 많아집니다.
 예를 들면 cde는 abcde를 해결할 때, cdefg를 해결할 때 한번씩 계산해야 하고,
 그러면 cde가 의존하는 c, de는 각각 세번씩 계산됩니다.

계산의 중복횟수는 분할의 깊이가 깊어질 수록 지수적으로 증가합니다.

이를 해결하기 위해 고안된 알고리즘 설계기법이 동적 계획법입니다.


2. 동적계획법 예시 - 이항계수의 계산

 이항계수는 n개의 서로 다른 원소 중 r개의 원소를 순서없이 골라내는 방법의 수를 나타낸 것으로,
아래 점화식이 성립합니다.

  


위 점화식을 코드로 짜면,

1
2
3
4
5
6
int bino(int n, int r)
{
    //기저 사례: n=r(모든 원소를 다 고르는 경우) r=0(고를 원소가 없는 경우)
    if(r==0 || n==r) return 1;
    return bino(n-1, r-1+ bino(n-1, r);
}
cs


이항 계수는 특성상 재귀 호출을 하게 되면 같은 값을 두 번 이상 계산할 일이 빈번합니다.

 

 

 (a) bino(4,2) 중복 제거 전

(b) bino(4,2) 중복 제거 후 

(a)에서 bino(2,1)는 bino(3,1)과 bino(3,2)에서 모두 호출됩니다.
bino(2,1)은 bino(1,0), bino(1,1)을 재귀 호출하여 이 경우도 두번씩 호출됩니다.
중복을 없애면 (b)를 얻을 수 있는데, 계산의 수가 줄어듬을 알 수 있습니다.

중복된 계산을 막기 위해 저장된 결과를 배열에 저장한 뒤,
다음에 계산이 필요할 때는 저장된 값을 불러옵니다
.
이러한 기법을 메모이제이션(memoization)이라고 부릅니다.

1
2
3
4
5
6
7
8
int cache[30][30];
int bino2(int n, int r)
{
    if(r==0 || n==r)      return 1;
    if(cache[n][r] != -1return cache[n][r];
    
    return cache[n][r] = bino2(n-1, r-1+ bino2(n-1, r);
}
cs




'Programming > Algorithm' 카테고리의 다른 글

Quick sort source  (0) 2016.01.17
메모_  (0) 2015.04.08
알고리즘 메모  (0) 2015.03.31
동적 계획법(Dynamic Programming)_1.개념  (0) 2015.03.26
분할정복(Divide and Conquer) - 2. 병합정렬  (0) 2014.06.25
분할정복(Divide and Conquer) - 1. 개념  (0) 2014.06.25

+ Recent posts

티스토리 툴바