Skip to content

Latest commit

 

History

History
109 lines (69 loc) · 2.92 KB

DynamicProgramming.md

File metadata and controls

109 lines (69 loc) · 2.92 KB

동적 계획법 (Dynamic Programming)이란?

큰 문제를 작은 문제로 나누고, 작은 문제들의 답을 이용해 큰 문제의 답을 구하는 방법론


등장 배경 : 피보나치 수열

DP

  • f(n-2) + f(n-1) = f(n)
  • 피보나치 수열 알고리즘은 재귀 함수 알고리즘을 활용
  • 항이 커져갈수록 굉장히 많은 중복 호출이 발생한다는 문제점 발생
  • 재귀 : 자기 자신을 호출하는 함수

[활용 조건]

어떤 경우에서 활용할 수 있을까?

DP를 사용하기 위해서는 아래 두 가지의 조건이 만족되어야 함

  1. 최적 부분 구조 (Optical Substructure)
  • 작은 문제들의 최적의 답을 이용해 큰 문제의 최적의 답을 구할 수 있어야 함
  • 즉, 큰 문제의 답에 작은 문제의 답이 포함되어 있음
  1. 부분 문제 반복 (Overlapping Subproblem)
  • 작은 문제의 답을 재활용하기 때문에 동일한 부분 문제가 반복적으로 나타나야함
  • 즉, 한 번 구한 답이 다음에 반복됨

[Memoization]

"컴퓨터 프로그램이 동일한 계산을 반복해야 할 때, 이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복 수행을 제거해 프로그램의 실행속도를 빠르게 하는 기술"

  • 동적 계획법의 핵심 개념
  • 기억하며 풀기
  • 작은 문제의 답을 메모하여 다음에 재사용하는 기법
  • 따라서 모든 작은 문제들은 단 한 번만 풀이되며, 이 답을 기억해야함

[풀이 종류]

  1. Bottom-Up
  • 작은 문제부터 차근 차근 해결해 큰 문제를 해결하는 방법
  • For문 활용
  • 재귀호출이 없어 시간과 메모리 절약 가능
  • But, 직관적 이해 힘듦
memo = [0]*100

for i in range(0, n):
    if i<2:
        memo[i] = i+1
       else :
        memo[i] = memo[i-1] + memo[i-2]
  1. Top-Down
  • 큰 문제부터 시작해 작은 문제로 쪼개며 문제를 해결하는 방법
  • 재귀 활용
  • 이전 계산 값이 있으면 쓰고 없으면 계산
  • 점화식 이해 쉬움
  • 최대 재귀 깊이 초과 에러 발생 가능
memo = [0]*100

# Idx 1부터라고 가정
def topDown(n):
    if n<=2:
        return n

    if memo[n] != 0 :
        return memo[n]

    memo[n] = topDown(n-1) + topDown (n-2)
    return memo[n]

각 방법은 어떨 때 유용할까?

Top-Down : 하위 문제가 복잡할 경우

Bottom-Up : 효율성을 고려할 경우


관련 문제

백준 2748 : 피보나치 수 2


[참고 자료]

DP 설명 1

DP 설명 2

DP 구현 코드