정글에서 온 개발자
이거 혹시 DP로 풀 수 있는 문제인가? 본문
- “프로그래밍” 은 테이블을 이용한 방법을 뜻한다. (컴퓨터와 관련이 없다.)
- 부분 문제의 해를 결합해 문제를 해결한다.
- 일반적으로 **최적화 문제(optimization problem)**에 적용한다.
최적화 문제
- 해와 값을 구분하자
- 문제의 풀이를 “해(Solution)” 라 한다.
- 그 풀이가 낸 답을 “값(Value)” 라 한다.
- 최적해는 각 해의 값 중 최적의 값을 내는 해이다.
- 최적의 값은 하나이지만 그 값을 내는 해는 여러개이다.
- 최단 거리(값)를 크루스칼, 프림 등 여러 방법(해)으로 풀 수 있다.
- 즉 최적화 문제는 여러개의 해를 가진다.
분할정복과의 비교
- 분할 정복은 서로 겹치지 않는(disjoint) 문제를 부분 문제로 분할한다.
- DP는 부분문제가 서로 중복될 때(부분 문제끼리 부분문제를 공유) 적용할 수 있다.
공통점
- 문제를 부분 문제로 분할한다.
- 부분 문제를 활용해 전체 문제를 해결한다.
그리디와의 비교
- DP는 부분 문제들의 최적해를 먼저 구한 후 선택한다.
- 그리디는 작은 부분 문제를 모두 풀려고 하지 않고 “그리디 선택” 을 한 다음에 결과로 얻어진 부분 문제만을 푼다.
공통점
- 최적 부분 구조를 가지고 있다.
DP의 요소
- 어떤 문제에 적용해야 할까?
- 최적해의 구조를 확인해야 하는데, 해는 여러개일 수 있으므로 각 해중에 최적 부분 구조를 가지는 게 있는지 (나올때까지)일일히 확인해야 한다.
- 실제 적용에서는 이렇게 하는 것보다 문제의 정의 자체에서 최적 부분 구조가 보일 가능성이 높다.
- 최단 경로, 최소 비용 등은 이미 최적 부분 구조가 있다는 것이 알려져 있다.
최적 부분 구조(Optimal substructure)
- 문제의 최적해가 그 안에 부분 문제의 최적해를 포함하고 있다.
- 고려하고 있는 부분 문제가 최적해를 구하는 데 사용되는 부분 문제르 ㄹ모두 포함하고 있는지 확인해야 한다.
- 또한 이 부분 문제들이 서로 독립적이여야 한다.
- 각 부분문제들이 자원을 공유하지 않아야 한다.
- ex) 최장 경로는 부분 문제에서는 한 번 지난 경로를 다른 부분 문제에서 한 번 더 지날 수 있으므로 자원을 공유한 것이고 독립적이지 않다. → DP로 풀수 없다.
최적 부분 구조 확인
- 문제에 대한 해는 선택하는 과정으로 만들어짐을 보임
- 선택을 어떻게 하맂는 모르겠지만, 최적해에 이를 수 있는 선택이 주어졌다고 가정
- 선택에서 발생하는 부분 문제가 어떤 것인지 정하고, 그 부분 문제의 범위를 잘 표현할 수 있는 방법을 정한다.
- 한 개의 최적해에 사용된 부분 문제들의 해가 최적이어야 함을 증명한다.
- “잘라 붙이기(cut-and-paste)” 방법을 이용한다.
최적 부분 구조의 구분
- 원래의 문제에 대한 최적해는 몇 개의 부분 문제를 사용하는가
- 원래 문제의 최적해에 사용할 부분 문제를 결정할 때 몇 가지 선택을 고려해야 하는가.
- 막대 자르기 문제 - 한개의 부분 문제, n(길이)가지 선택
- 행렬 곱 문제 - 두개 의 부분 문제(두개가 합쳐짐), j-i의 선택
잘라 붙이기 방법
- 각 부분 문제의 최적해가 아닌 부분을 잘라내고(cutting-out), 거기에 최적해를 붙이면(pasting-in) 원래의 해보다 좋은 해를 얻게 된다.
중복되는 부분 문제(Overlapping subproblems)
- 부분 문제들의 범위가 “작아야” 한다
- 재귀 알고리즘이 같은 문제를 계속해서 풀게 된다.
- 그리고 그 문제를 테이블에 저장한다.
DP를 푸는 4단계
- 최적해의 구조의 특징을 찾는다. (최적해는 여러개가 될 수 있음에 주의)
- 최적해의 값을 재귀적으로 정의한다.
- 최적해의 값을 일반적으로 상향식(bottom-up)방법으로 계산한다.
- (필요한 경우)계산된 정보들로부터 최적해(최적값을 구한 방법)를 구성한다.
DP 구현의 두가지 방법
하향식(Top-down)
- 재귀로 푼다.
- 각 부분 문제의 결과를 배열이나 해시 테이블에 저장한다.(메모이제이션)
- 부분 문제 그래프를 깊이-우선 탐색 하는 것으로 볼 수 있다.
상향식(Bottom-up)
- 부분 문제의”크기”가 작은 것부터 올라간다.
- 부분 문제를 크기별로 정렬한=해야 한다.
- 특정 문제를 풀기 전에 그 해에 영향을 미치는 더 작은 부분 문제를 모두 풀어 그 해를 저장해놓는다.(타뷸레이션)
- 상향식이 하향식보다 함수 호출에 대한 오버헤드가 작다.(재귀는 계속 호출하므로)
- 따라서 다 나은 상수 비율을 갖는다.
- 부분 문제 그래프를 위상 정렬의 역순으로 푼다고 볼 수 있다.
도움이 되는 개념
부분 문제 그래프
- 관련된 부분 문제의 집합과 부분 문제가 어떻게 연관되어 있는지 나타내는 그래프
- 하향식 재귀트리에서 같은 부분 문제를 한 정점으로 합친 그래프다.
- 각 정점은 부분 문제에 해당
- 간선은 한 부분 문제에 대해 해야할 선택
더 공부해봐야 할 것들
- 알고리즘 책에 나온 DP의 유명한 알고리즘들
- 비터비 알고리즘 등
출처
- Introduction To Algorithms (3rd edition)
'정리' 카테고리의 다른 글
Spring 큰 그림 그려보기 (1) | 2024.01.05 |
---|---|
[pintOS]-Priority Inversion, Multiple, Nested 정리 (1) | 2023.12.05 |
P,NP,NPC 문제 (2) | 2023.11.01 |
이진탐색트리(균형, 트립) 정리 (1) | 2023.10.23 |
트리 개관 (1) | 2023.10.23 |