◇ 설명
◎ 동적 계획법 ( DP ( Dynamic Programming ) )
- 복잡한 큰 문제를 해결하기 위해 작은 문제로 분할할 때, 중복되는 작은 문제들을 한 번만 계산하도록 캐싱( 메모이제이션 )함으로써
중복 계산을 피해 효율성을 높이는 알고리즘 설계 기법
- 하향식( top-down ), 상향식( bottom-up )이 있음
┌ top-down 방식 : 큰 문제를 재귀적으로 계산
└ bottom-up 방식 : 작은 부분부터 시작하여 이전의 결과를 이용하여 점진적으로 계산
- 큰 문제를 작은 부분 문제들로 나눈다는 것은 분할정복법과 비슷하지만, 차이가 있음
∎ 동적 계획법 -- 부분 문제들이 같은 부분 문제에 의존함 ( -> 중복 계산이 많아짐 )
∎ 분할 정복 -- 부분 문제들이 서로 독립적이다. 연관이 없다
◎ 메모이제이션 ( Memoization )
: 계산 결과를 캐시에 저장하고, 저장된 값을 사용하는 것
( 단, 입력이 고정되어 있을 때 그 결과가 항상 같은 함수( 참조적 투명 함수 )의 경우에만 적용할 수 있음
◎ 동적 계획법 레시피
- 동적 계획법 알고리즘을 만드는 첫 단계는 해당 문제를 재귀적으로 해결하는 완전 탐색 알고리즘을 만드는 것
1. 주어진 문제를 완전 탐색을 이용해 해결
2. 중복된 부분 문제를 한 번만 계산하도록 메모이제이션 적용
◇ 코드
ex) 피보나치 수열
public class Test { // 피보나치 수열
static int[] cache;
// 일반 재귀
public static int fibonacci1( int n ) {
if( n == 0 || n == 1 ) return n;
return fibonacci1( n - 2 ) + fibonacci1( n - 1 );
}
// 동적 계획법
public static int fibonacci( int n ) { // top_down
if( n == 0 || n == 1 ) return n;
if( cache[n] != -1 ) return cache[n];
return cache[n] = fibonacci( n - 2 ) + fibonacci( n - 1 );
}
public static int fibonacci2( int n ) { // bottom_up
if( n == 0 || n == 1 ) return n;
int a = 0, b = 1, c = 0, i;
for( i = 2; i <= n; i++ ) {
c = a + b;
a = b;
b = c;
}
return c;
}
public static void main(String[] args) {
int n = 5;
cache = new int[n+1];
for( int i = 0; i < n+1; i++ )
cache[i] = -1;
System.out.println( fibonacci( n ) );
}
}
ex) 이항 계수
public class Test { // 이항 계수
static int[][] cache;
// 일반 재귀
public static int bino1( int n, int r ) {
if( n == r || r == 0 ) return 1;
return bino1( n-1, r-1 ) + bino1( n-1, r );
}
// 동적계획법
public static int bino( int n, int r ) {
if( n == r || r == 0 ) return 1;
if( cache[n][r] != -1 ) return cache[n][r];
return cache[n][r] = bino( n-1, r-1 ) + bino( n-1, r );
}
public static void main(String[] args) {
int n = 5, r = 3;
cache = new int[n+1][r+1];
for( int i = 0; i < n+1; i++ )
for( int j = 0; j < r+1; j++ )
cache[i][j] = -1;
System.out.println( bino1( n, r ) );
System.out.println( bino( n, r ) );
// 이항 계수 : n개 중 r개를 순서 없이 고는 경우의 수
// 기저사례 : n = r ( 모든 원소를 다 고르는 경우 ) or r = 0 ( 고를 원소가 없는 경우 )
}
}
◇ 출처
- 설명 -- 알고리즘 문제 해결 전략 ( 구종만 )
- 코드 -- 〃, 코딩 인터뷰 완전 분석 ( 게일 라크만 맥스웰 )
'컴퓨터 공학 ( Computer Science ) > 알고리즘 ( Algorithm )' 카테고리의 다른 글
[알고리즘 기법] 백트래킹 ( 되추적 방법 ) ( Backtracking ) (0) | 2021.03.20 |
---|---|
[알고리즘 기법] 분할정복법 ( Divide and Conquer ) (0) | 2021.03.20 |
[알고리즘 기법] 탐욕법 ( 그리디 : Greedy ) (0) | 2021.03.20 |
[알고리즘 기법] 완전탐색 ( 브루트 포스 : Brute-Force ) (0) | 2021.03.19 |
[알고리즘] 정렬 ( Sort ) (0) | 2021.03.19 |