다이나믹 프로그래밍 문제를 해결할 수 있는 5가지 단계(Steps)
다이나믹 프로그래밍 문제를 공부할 때 좋은 교육용 자료를 해외 사이트에서 찾아서 공유한다.
▶ 다이나믹 프로그래밍 문제를 해결할 수 있는 5가지 단계(Steps): https://www.youtube.com/watch?v=aPQY__2H3tE
▶ 예시 문제: Longest Increasing Subsequence (LIS)
LIS는 증가하는 가장 긴 부분 수열을 찾는 문제다. 예를 들어 [3, 1, 8, 2, 5]라는 수열이 있을 때, LIS는 [1, 2, 5]이다.
[1단계] Visualize examples (예제를 시각화하기)
다이나믹 프로그래밍은 그래프 형태로 표현하면 이해하기 쉬운 경우가 많다. 예를 들어 LIS는 DAG (Directed Acyclic Graph) 그래프 형태로 표현이 가능하다.
[2단계] Find an appropriate subproblem (적절한 부분 문제를 찾기)
모든 증가하는 부분 수열은 원본 수열(original sequence)의 부분집합이다. 또한 모든 LIS는 시작점(start)과 끝점(end)이 존재한다. 따라서 다음과 같이 부분 문제를 정의하는 것이 좋다.
LIS[k] = 인덱스 k에서 끝나는 LIS의 길이
구체적으로 [3, 1, 8, 2, 5]라는 수열이 있을 때 LIS 값은 다음과 같다.
LIS[0] = 1
LIS[1] = 1
LIS[2] = 2
LIS[3] = 2
LIS[4] = 3
[3단계] Find relationships among subproblems (부분 문제 간의 관계 찾기)
[3, 1, 8, 2, 5]를 생각해보자. 이때 LIS[4]를 해결하기 위해서는 LIS[0] ~ LIS[3]를 이미 계산한 상태여야 한다. 또한 arr[4]보다 arr[2]가 더 크기 때문에, arr[2]를 제외한 인덱스 0, 1, 3만 고려해야 한다.
따라서 LIS[4] = 1 + max{LIS[0], LIS[1], LIS[3]}으로 정의가 가능하다. 결과적으로 LIS[4] = 3인 것을 알 수 있다.
[4단계] Generalize the relationship (관계를 일반화하기)
이러한 사실을 토대로 유추하건데, LIS[x] = 1 + max{LIS[k] | k < x, arr[k] < arr[x]}로 정리가 가능한 것을 알 수 있다.
[5단계] Implement by solving subproblems in order (코드로 구현하기)
결과적으로 원소의 개수가 N개일 때, LIS[0] ~ LIS[N - 1] 중에서 가장 큰 값을 고르면 된다.
def lis(arr):
lis = [1] * len(arr)
for i in range(1, len(lis)):
subproblems = [lis[k] for k in range(i) if arr[k] < arr[i]]
lis[i] = 1 + max(subproblems, default=0)
return max(lis, default=0)
print(lis([3, 1, 8, 2, 5]))
'기타' 카테고리의 다른 글
홈택스 세금 신고/납부 관련 무료 상담 방법 - 국세청 국세상담센터(126), 국세청 인터넷 상담 및 마을 세무사에 대해 알아보자! (0) | 2021.06.02 |
---|---|
뉴스 저작권에 대하여 알아보자! 뉴스토어(NEWSTORE)에서 온라인 뉴스 저작권을 구매하는 방법 소개 (0) | 2021.06.02 |
어떠한 재귀 문제(Recursive Problem)도 해결할 수 있는 5가지 단계(Steps) (0) | 2021.06.02 |
예전에 신고했던 종합소득세 신고서 내용 확인하는 방법 (0) | 2021.06.01 |
종합소득세 신고 기간에 늦었을 때 가산세는? 기한 후 신고 방법 소개! (0) | 2021.06.01 |