•
개념
◦
다이나믹 프로그래밍이란 하나의 문제를 단 한 번만 풀도록하는 알고리즘이다.
⇒ 이름이랑 알고리즘이랑 상관없다 이름 붙인 사람이 그냥 멋있어서 붙인거다.
◦
큰 문제를 작은 문제로 쪼개서 해결하는 과정에서, 작은 문제를 단 한 번만 푸는 것이다.
⇒ 분할 정복과 유사하다고 생각할 수 있으나 분할 정복의 경우, 중복이 발생하지 않을 수 있다.
•
사용 조건
◦
DP가 적용되기 위해서는 2가지 조건을 만족해야 한다.
▪
Overlapping Subproblems
▪
Optimal Substructure
◦
Overlapping Subproblems ⇒ 작은 문제들이 중복해서 발생한다.
▪
DP는 기본적으로 문제를 이미 연산이 종료된 최소 단위로 나누어 전체 답을 계산한다. 따라서 동일한 작은 문제들이 반복해서 나타나는 경우 사용 가능하다.
▪
이진 탐색과 피보나치 수열을 예로 들 수 있다.
•
이진 탐색은 특정 데이터를 정렬된 배열 내에서 그 위치를 찾기 때문에 그 위치를 찾은 후 바로 반환할 뿐 재사용하지는 않는다.
•
피보나치 수열은 특정 값에 대한 연산이 반복적으로 나타나는 구조이다.
◦
Optimal Substructure ⇒ 최적의 하위 구조는 최적의 솔루션으로부터 나온다.
▪
부분 문제의 최적 결과 값을 사용해 전체 문제의 최적 결과를 낼 수 있는 경우를 의미한다. 특정 문제의 정답은 문제의 크기에 상관없이 항상 동일하다.
•
그리디에서 본거 그거 맞다.
◦
DP는 특정한 경우에 사용하는 알고리즘이 아니라 하나의 방법론이므로 다양한 문제해결에 쓰일 수 있다.
◦
일반적으로 DP를 사용하기 전에는 아래의 과정을 거쳐 진행할 수 있다.
▪
1) DP로 풀 수 있는 문제인지 확인한다.
•
위 조건들에 부합하는 문제인지 확인해야 한다.
•
보통 특정 데이터 내에서 최대화, 최소화 계산(최적화)을 하거나 데이터를 세야(카운팅)한다거나 확률 등의 계산의 경우에 DP를 사용할 수 있다.
▪
2) 문제의 변수 파악
•
현재 변수에 따라 그 결과 값을 찾고 전달하여 재사용하는 것이 DP다. 즉 문제 내 변수의 개수를 알아내야한다는 것인데, 이를 state를 결정한다고 한다.
◦
피보나치 수열에서는 n 번째 숫자를 구하는 것이므로 n이 변수가 된다.
▪
3) 변수 간 관계식 만들기(점화식)
•
변수들에 의해 결과 값이 달라지지만 동일한 변수값인 경우 결과는 동일하다. 그 결괏값을 그대로 이용하므로 그 관계식을 만들어낼 수 있어야 한다.
▪
4) 메모하기(memoization or tabulation) → 메모이제이션 또는 타뷸레이션 둘 중 하나로 해결할 수 있다.
•
변수 간 관계식까지 정상적으로 생성되었다면 변수의 값에 따른 결과를 저장해야한다. 이를 메모이제이션이라고 한다.
•
이 결과 값을 저장할때는 보통 조회가 빠른 배열을 사용하며 배열의 차원은 변수의 갯수에 따라 다양할 수 있다.
▪
5) 기저 상태 파악하기
•
가장 작은 문제에 대한 결괏값을 알아내야 한다. 보통 직접 계산해보는 경우가 많다.
▪
6) 구현하기
•
DP는 보통 2가지 방식으로 구현된다.
◦
Bottom-Up - 반복문 사용 → 타뷸레이션
◦
Top-Down - 재귀 사용 → 메모이제이션