Explaining Dynamic Programming "동적 프로그래밍 (DP)"

moon.kick·2025년 5월 3일

Explaining Dynamic Programming

User mentioned "동적 프로그래밍 (DP)", and they likely want an explanation. I think they’re looking for an in-depth discussion on DP—what it is, when to use it, and how to spot DP problems like Fibonacci, coin change, and knapsack. I'll make sure to clarify the difference between memoization vs tabulation, and provide clear examples along with code.

I'll keep the tone energetic and structured to match their previous vibe, maybe even using some Korean examples for familiarity!

11초 동안 생각함

🎲 Dynamic Programming (DP) 완전 공략 가이드
(“암기” → “감각” → “응용” 순으로 설계했어요. 편하게 따라오세요!)


1. DP란?

키워드한줄 정의직관
Overlapping Sub-problems같은 계산을 계속 반복한다“F₄를 구하려는데 F₂를 두 번, F₃도 두 번…”
Optimal Sub-structure큰 문제의 최적해가 작은 문제의 최적해로 조합된다“0-1 배낭: ‘남은 무게 w에서 최대 가치’ → 한 물건 넣느냐 마느냐”

DP = “한 번 푼 건 저장해 두고, 작은 최적해를 재사용해 큰 최적해를 만든다.”


2. 두 얼굴: Memoization vs Tabulation

방식구현장점단점
Top-Down (Memoization)재귀 + 딕셔너리(배열) 캐시 코드 직관적, 필요한 것만 계산재귀 깊이 = 호출 스택 사용, 함수 호출 오버헤드
Bottom-Up (Tabulation)작은 값부터 ↑ 배열 채우기스택 OK, 상수 오버헤드 ↓복잡한 상태일 때 순회 순서 설계 필요

3. DP 문제 해결 4-Step 템플릿

  1. State 정의

    • 무엇이 변할 때 새로 계산해야 하나?” → 보통 인덱스·용량·잔돈 등이 변수
  2. Recurrence(Transition) 수립

    • 현재 상태를 더 작은 상태로 분해
  3. Base Case

    • 가장 작아서 바로 답을 알 수 있는 상태
  4. Implementation

    • Top-Down 혹은 Bottom-Up + 캐시 배열 사이즈 점검

📌 tip: “상태 수 × 상태당 연산” = 시간 복잡도, 캐시 배열 크기 = 공간 복잡도!


4. 대표 예제 ⓔ코드 & 직감

4-1. 피보나치 (1D DP, O(n))

def fib(n):
    if n < 2:  # base
        return n
    dp = [0, 1] + [0]*(n-1)
    for i in range(2, n+1):
        dp[i] = dp[i-1] + dp[i-2]
    return dp[n]
# 공간 최적화 → 두 변수만 써도 OK

4-2. 0-1 Knapsack (2D DP, O(nW))

def knapsack(items, W):
    # items = [(w,v), …]
    n = len(items)
    dp = [[0]*(W+1) for _ in range(n+1)]
    for i,(w,v) in enumerate(items, 1):
        for cap in range(W+1):
            if w > cap:            # 못 넣음
                dp[i][cap] = dp[i-1][cap]
            else:                  # 넣을지 말지
                dp[i][cap] = max(dp[i-1][cap],
                                 dp[i-1][cap-w]+v)
    return dp[n][W]
# 1D 배열 cap 역순 순회로 공간 O(W) 가능

4-3. LIS(최장 증가 부분수열) – 이분 탐색 결합 (O(n log n))

  1. 길이 k인 증가 subseq의 최소 끝값을 dp[k]로 유지
  2. 매 원소마다 bisect_left(dp, x) 위치 갱신

DP + 그리디/이분 = 하이브리드 패턴도 많습니다!


5. 흔한 패밀리별 초심자 → 중급 러닝 코스

단계문제 유형키 포인트
Level 11D: Climbing Stairs, House Robber, Fibonacci점화식 바로 보이도록 훈련
Level 22D 그리드: Unique Paths, 최소비용 경로방향성·경계 조건
Level 3배낭류: 0-1, Unbounded, Partition Equal Subset용량(capacity) 축
Level 4문자열: LCS, Edit Distance, Palindrome Partitioning두 인덱스(i, j) → 2D
Level 5DP + 비트마스크/트리: Traveling Salesman, Tree DP상태 압축·트리 순회
Level 6DP + 슬라이딩 윈도: 수열 합 최적화, Convex Hull Trick점화식 가속, deque

6. 시간·공간 복잡도 감 잡기

유형상태 수per-state 연산TS
1D (index)nO(1)O(n)O(n) → O(1) 최적화 가능
2D (i, j)O(1)O(n²)O(n²)
배낭 (i, W)n·WO(1)O(nW)O(nW) → O(W)
비트마스크n·2ⁿO(1)O(n 2ⁿ)O(n 2ⁿ)

7. 디버깅 & 실전 팁

  1. 배열 범위 먼저: dp 크기 부족 → IndexError 💥

  2. Base Case 체크: n=0,1 시험 입력 필수

  3. 메모리 초과(ML) 나면?

    • 테이블 압축, defaultdict sparse 캐시, 비트마스크 등
  4. Visualize: 표·격자 그려서 상태 전이 화살표 직접 그려보면 속이 뻥!


8. 연습 플랫폼 & 추천 문제 세트

난이도사이트문제 리스트(예시)
입문백준 1463, 1699, 25791D 점화식
중급LeetCode 62, 198, 300, 518그리드·배낭·LIS
고급백준 2098(TSP), 13913(경로 출력)비트마스크·경로 추적
도전AtCoder DP Contest (A~Z)모든 유형 한꺼번에

9. 다음 단계 👉 “DP로 풀 수 있나?” 감각 기르기

  • 반복되는 서브문제? 재귀적으로 정의 가능한가?
  • 최적화 기준(최댓값·최소값·경로 수 등)이 부분 결과의 최적 값 조합으로 표현되나?
  • 탐욕, 분할정복 실패 시 DP를 의심해 보세요!

💡 궁금한 점 / 풀고 싶은 문제를 던져주시면, 상태 정의부터 코드 리뷰까지 함께 해드릴게요.
도장 깨기 시작해 볼까요? 🚀

profile
@mgkick

0개의 댓글