[알고리즘] 동적 계획법(Dynamic Programming)
1. 동적 계획법(Dynamic Programming, DP)이란?
동적 계획법(Dynamic Programming, DP)은 큰 문제를 작은 문제로 나눠서 푸는 알고리즘 설계 기법이다.
분할 정복 알고리즘과 차이는 메모이제이션의 필요여부다.
분할 정복 알고리즘은 계산된 소문제의 출력값을 저장하지 않는다. (1회용)
동적 계획법은 계산된 소문제의 출력값을 저장해서 다음 계산때 사용한다. (재활용)
동적 계획법을 적용시킬 수 있는 예시는 다음과 같다.
- f(a,b) = f(a-1,b) + f(a,b-1) (a,b >= 1 )
- f(0,0) = 1, 임의의 자연수 n에 대해 f(n,0) = f(0,n) = 1

위 그림에서 초록색으로 칠해논 부분이 문제를 작은 문제로 분할하는 과정에서 중복되는 문제다.
그림의 패턴만 봐도 a, b의 값이 커지면 커질수록 중복되는 작은 문제들이 기하급수적으로 늘어날 것임을 짐작할 수 있다.
2. 문제로 살펴보는 동적 계획법
동적 계획법을 설명하기 위한 대표적인 문제가 피보나치 수열이다. 피보나치 수열은 아래와 같은 조건을 가진다.
f(1) = 1 f(2) = 1 f(n) = f(n-1) + f(n-2) // n > 2
위의 조건을 살펴보면 매 연산마다 중복되는 작은 문제들이 생겨난다. 피보나치 수열을 동적 계획법으로 접근해보자.
동적 계획법은 2가지 방법으로 접근할 수 있다.
- Top-down : 큰 문제부터 시작해 작은 문제로 분할해가며 푸는 방법
- Botton-up : 작은 문제를 풀어가며, 점점 쌓아가 큰 문제를 푸는 방법
코드로 살펴보자
Top-down 방식
// Top-down int memo[100] = { 0, }; // 메모이제이션 int fibonacci(int n) { if (n == 1 || n == 2) return 1; if (memo[n] != 0) return memo[n]; // 메모이제이션에 이전에 계산해논 값이 있다면 재활용 !! memo[n] = fibonacci(n - 1) + fibonacci(n - 2); return memo[n]; }
Bottom-up 방식
// Bottom-up int memo[101] = { 0, }; // 메모이제이션 int fibonacci(int n) { if (n == 1 || n == 2) return 1; memo[1] = 1; // 해석을 직관적으로 하기 위해 0번이 아닌 1번부터 시작 memo[2] = 1; for (int i = 3; i <= n; i++) { memo[i] = memo[i - 1] + memo[i - 2]; } return memo[n]; }
지금까지 DP 문제를 풀 때 항상 Bottom-up 방법으로 접근했었는데 Top-down 방법으로 접근하는 것도 연습해야겠다. 어쨋든 동적 계획법을 이용해 시간 복잡도를 O(n)으로 만들었다. 슬라이딩 윈도우 기법을 쓰면 공간 복잡도를 O(1)로 만들 수 있다는데, 이건 차차 공부해봐야지
3. 참고자료
'Algorithm > Theory' 카테고리의 다른 글
[자료구조] 그래프(Graph) (0) | 2019.12.10 |
---|---|
[자료구조] 서로소 집합(Disjoint-Set) (0) | 2019.11.13 |
[자료구조] 이분 그래프 (Bipartite Graph) (0) | 2019.09.24 |
[알고리즘] 백트래킹(Backtracking) (0) | 2019.09.02 |
[자료구조] 쿼드 트리 (Quad Tree) (0) | 2019.08.29 |
댓글
이 글 공유하기
다른 글
-
[자료구조] 그래프(Graph)
[자료구조] 그래프(Graph)
2019.12.10그래프(Graph) 그래프란 연결되어 있는 객체 간의 관계를 표현하는 자료구조이다. 그래프의 종류는 크게 3가지로 나뉜다. 무방향 그래프(undirected graph) 방향 그래프(directed graph) 가중치 그래프(weighted graph) 더 넘어가기 전에, 그래프에서 알아야할 용어가 있다. 싸이클 분절점 위의 개념들을 익혔다면 그 다음으로 익혀야할 건 그래프의 탐색이다. 그래프에서 탐색은 가장 기본적인 연산이지만, 많은 문제들이 단순히 그래프의 노드를 탐색하는 것으로 해결될만큼 중요하다. 그래프의 탐색 방법은 2가지다. (2가지 밖에 없다 !) 깊이 우선 탐색(DFS : Depth First Search) 너비 우선 탐색(BFS : Breath First Search) DFS/BFS에 대… -
[자료구조] 서로소 집합(Disjoint-Set)
[자료구조] 서로소 집합(Disjoint-Set)
2019.11.13 -
[자료구조] 이분 그래프 (Bipartite Graph)
[자료구조] 이분 그래프 (Bipartite Graph)
2019.09.24 -
[알고리즘] 백트래킹(Backtracking)
[알고리즘] 백트래킹(Backtracking)
2019.09.02
댓글을 사용할 수 없습니다.