동적 계획법::메모이제이션

폭풍저그머성찡 ㅣ 2020. 5. 28. 00:29

동적 계획법이란::

문제를 같은 해법을 가지는 재귀적인 덩어리로 분할 해서 각각 분할된 부분 문제들을 해결하고

 

이를 합쳐나가며 전체의 해를 찾는 풀이법을 말한다. 완전 탐색과 다른 점은 이미 계산된 해를 계산하지 않는다는 점이다.

 

이 때, 나눠진 부분 문제들이 같은 문제 일 경우, 의미없는 중복계산이 발생되어 코드가 느려진다.

 

메모이제이션은 각각의 부분문제들의 대한 해법을 따로 테이블에 계산해놓고 같은 부분 문제가 나올 경우,

 

그 해를 사용하는 알고리즘 기법이다.

 

이를 통해서 중복된 계산을 피하고 백트래킹으로는 답을 구하기 힘든 문제들을 비교적 쉽게 계산 할 수 있다.

 

중복 계산을 소거하기 위해서 사용되는 대표적인 기법이다.

 

부분 문제에 대한 해를 구했을 경우 그 해를 저장해놓고 이 후, 풀이과정에서 같은부분 문제가 다시 제기 되었을 경우, 

 

저장된 해를 사용하므로써 중복 계산을 피한다.

 

아래코드는 피보나치를 구하는 bottom-up 방식의 재귀호출이다.

dp[0] = 1;
dp[1] = 1;
int fibo(int n) {
	 if(n <= 1) return 1;
     return fibo(n - 1) + fibo(n - 2);
}

이 코드의 동작과정을 복기하며 문제점을 찾아보자.

fibo(6)

fibo(5) + fibo(4)

fibo(4) + fibo(3)  fibo(3) + fibo(2)

fibo(3) + fibo(2)   fibo(2) + fibo(1)  fibo(2) + fibo(1)  fibo(1) + fibo(0)

fibo(2) + fibo(1)   fibo(1) + fibo(0)   fibo(1) + fibo(0)

아래와 같이 각 층마다 호출 될 것이다. 이 때, fibo(4), fibo(3), fibo(2)의 중복된 호출은 필요없는 계산들이다.

 

따라서 아래와 같이 최적화가 가능하다.

dp[0] = 1;
dp[1] = 1;
int memoization[100] = { -1, };
int fibo(int n) {
	 if(n <= 1) return 1;
     if(memoization[n] != -1) return memoization[n];
     return memoization[n] = fibo(n - 1) + fibo(n - 2);
}

memoization 배열에 n번째 피보나치수를 저장해놓고 그 값이 있다면 추가적인 호출을 하지 않도록 한다.

 

메모이제이션은 동적 계획법의 핵심이 되는 기법으로 PS를 할 때에도 이 기법을 어디에 적용할지 항상 고민하며 

 

풀이해야한다.

 

 

'Algorithm > Algorithm 이론' 카테고리의 다른 글

KMP Best-Practice  (2) 2023.02.16
동적계획법 PS 팁  (0) 2020.05.30
[위상정렬]  (0) 2019.12.17
[Spanning Tree]  (0) 2019.12.13
[기타] 라인 스윕  (0) 2019.12.05