나폴레옹은 자신보다 큰 군대를 상대할 때, 적을 작게 분할해서 각각 공격하는 방식으로 승리했습니다. 동적 계획법도 마찬가지로 큰 문제를 작은 문제로 쪼개서 해결합니다!
시험 범위가 300페이지라면, 한 번에 외우려 하면 힘듭니다. 하지만 10페이지씩 나눠서 공부하고, 앞에서 공부한 내용을 메모해두면 훨씬 효율적입니다. 동적 계획법은 바로 이런 방식입니다!
Napoleon defeated larger armies by dividing them into smaller groups and attacking each one. Dynamic Programming works the same way — break a big problem into smaller ones!
If the exam covers 300 pages, memorizing all at once is hard. But studying 10 pages at a time and keeping notes of what you've learned is much more efficient. That's exactly how DP works!
당신은 보물섬에 도착했습니다! 보석이 가득하지만, 배낭에는 최대 7kg까지만 담을 수 있습니다. 어떤 보석을 담아야 가장 비싼 조합이 될까요?
| 보석 | 무게(kg) | 가격(억 원) |
|---|---|---|
| 금괴 | 6 | 13 |
| 수정 | 4 | 8 |
| 루비 | 3 | 6 |
| 진주 | 5 | 12 |
배낭 최대 무게: 7kg
You've arrived at Treasure Island! There are lots of gems, but your bag can hold at most 7kg. Which gems should you take to get the most expensive combination?
| Gem | Weight(kg) | Value(billion) |
|---|---|---|
| Gold Bar | 6 | 13 |
| Crystal | 4 | 8 |
| Ruby | 3 | 6 |
| Pearl | 5 | 12 |
Max bag weight: 7kg
4자리 자물쇠 비밀번호를 모르면? 0000부터 9999까지 하나씩 다 시도해보면 반드시 열립니다. 이것이 브루트 포스(무차별 대입)입니다!
모든 가능한 조합을 전부 나열한 후, 그 중에서 최선의 답을 찾는 방법입니다. 확실하지만 매우 느립니다!
각 보석을 "넣는다/안 넣는다" 2가지 선택이 있으므로:
| 조합 | 금괴 | 수정 | 루비 | 진주 | 무게 | 가격 | 가능? |
|---|---|---|---|---|---|---|---|
| 1 | X | X | X | X | 0 | 0 | O |
| 2 | X | X | X | O | 5 | 12 | O |
| 3 | X | X | O | X | 3 | 6 | O |
| 4 | X | X | O | O | 8 | - | X(초과) |
| 5 | X | O | X | X | 4 | 8 | O |
| 6 | X | O | X | O | 9 | - | X(초과) |
| 7 | X | O | O | X | 7 | 14 | O |
| ... | 나머지 조합도 계산... | ||||||
Don't know the 4-digit code? Try every number from 0000 to 9999 — you'll eventually open it. That's brute force!
List ALL possible combinations, then pick the best answer. It guarantees the right answer but is very slow!
Each gem has 2 choices: "include" or "exclude":
As the number of items grows, the combinations explode exponentially. Time complexity is O(2n).
뷔페에 갔을 때, 가장 비싼 음식부터 먹는 전략! 눈앞의 최고를 바로 선택하는 방법이 탐욕 알고리즘입니다.
매 순간 가장 좋아 보이는 것을 선택하는 방법입니다. 빠르지만, 항상 최적의 답을 보장하지는 않습니다!
At a buffet, eat the most expensive dishes first! Always picking the best-looking option right now is the Greedy approach.
At each step, choose what looks best at the moment. It's fast but doesn't always guarantee the optimal answer!
모든 경우의 수를 시도
정확하지만 매우 느림
O(2n)
눈앞의 최선만 선택
빠르지만 틀릴 수 있음
O(n log n)
체계적 + 메모이제이션
정확하고 빠름!
O(n × W)
| 비교 항목 | 브루트 포스 | 탐욕 알고리즘 | 동적 계획법 |
|---|---|---|---|
| 정확성 | 항상 정확 | 가끔 틀림 | 항상 정확 |
| 속도 | 매우 느림 | 빠름 | 빠름 |
| 시간복잡도 | O(2n) | O(n log n) | O(n × W) |
| 보석 4개 | 16회 | 4회 | 28회 |
| 보석 40개 | 1조 회! | 40회 | 280회 |
n: 물건의 수, W: 배낭의 최대 무게
Try every combination
Accurate but very slow
O(2n)
Pick local optimum
Fast but sometimes wrong
O(n log n)
Systematic + Memoization
Accurate AND fast!
O(n × W)
| Criteria | Brute Force | Greedy | DP |
|---|---|---|---|
| Accuracy | Always correct | Sometimes wrong | Always correct |
| Speed | Very slow | Fast | Fast |
| Complexity | O(2n) | O(n log n) | O(n × W) |
| 4 items | 16 ops | 4 ops | 28 ops |
| 40 items | 1 trillion! | 40 ops | 280 ops |
n: number of items, W: max bag weight
보물섬에서 보석을 36개 더 발견했습니다! 이제 총 40개의 보석 중에서 골라야 합니다.
빠르긴 하지만, 앞에서 봤듯이 최적의 답을 보장하지 않습니다.
You found 36 more gems on the island! Now you need to choose from a total of 40 gems.
It's fast, but as we saw, it doesn't guarantee the optimal answer.
DP avoids redundant work by remembering what it already calculated. Instead of checking every combination, it builds the answer step by step, reusing previous results.
큰 문제의 최적의 답이 작은 문제들의 최적의 답으로 구성된다.
서울→부산 최단 경로가 서울→대전→부산이라면, 서울→대전 구간도 최단 경로여야 합니다. 전체 최적이 부분 최적을 포함합니다!
같은 작은 문제가 여러 번 반복해서 나타난다.
미적분 문제를 풀다 보면 "덧셈, 곱셈"을 계속 반복합니다. 매번 덧셈을 처음부터 배우지 않고 이미 아는 것을 활용하죠. 이것이 메모이제이션!
The optimal solution to the big problem is made up of optimal solutions to smaller subproblems.
If the shortest Seoul→Busan route goes through Daejeon, then the Seoul→Daejeon segment must also be the shortest. The whole optimal solution contains optimal sub-solutions!
The same small problem appears repeatedly during computation.
When solving calculus problems, you keep repeating addition and multiplication. You don't re-learn addition each time — you reuse what you already know. That's memoization!
보석이 5개일 때 브루트 포스로 확인해야 하는 경우의 수는?
보석이 n개이면 경우의 수는 2n이므로, 25 = 32가지입니다.
배낭 최대 무게가 10kg일 때, 다음 물건으로 탐욕 알고리즘을 적용하면?
물건A: 7kg, 10만원 / 물건B: 5kg, 6만원 / 물건C: 5kg, 6만원
탐욕: 가장 비싼 A(10만원) 먼저 선택 → 남은 3kg → B,C 불가 → 10만원
최적: B(6만원) + C(6만원) = 10kg → 12만원!
탐욕 알고리즘이 최적이 아닌 답을 줍니다.
메모이제이션의 핵심 아이디어를 한 줄로 설명하세요.
한 번 계산한 결과를 저장해두고, 같은 계산이 필요하면 다시 풀지 않고 저장된 답을 재사용하는 기법입니다.
How many combinations must brute force check with 5 gems?
Each gem: include or exclude → 2 choices
25 = 32 combinations
Bag capacity 10kg. Item A: 7kg/$10, B: 5kg/$6, C: 5kg/$6. What does Greedy pick?
Greedy: Picks A ($10) first → 3kg left → can't fit B or C → $10
Optimal: B + C = 10kg → $12!
Greedy gives a suboptimal answer.
Explain memoization in one sentence.
Store computed results and reuse them when the same calculation is needed again, avoiding redundant work.
성적표에 학생(행)과 과목(열)을 배치하듯, DP 테이블도 행(보석)과 열(배낭 무게)로 구성합니다. 처음에는 모두 0으로 시작합니다!
행: 보석 종류 (없음, 금괴, 수정, 루비, 진주) → 5행
열: 배낭 무게 (0kg ~ 7kg) → 8열
| 보석\무게 | 0kg | 1kg | 2kg | 3kg | 4kg | 5kg | 6kg | 7kg |
|---|---|---|---|---|---|---|---|---|
| 없음(0) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 금괴(1) | 0 | |||||||
| 수정(2) | 0 | |||||||
| 루비(3) | 0 | |||||||
| 진주(4) | 0 |
Just as a report card has students (rows) and subjects (columns), the DP table has gems (rows) and bag weights (columns). Everything starts at 0!
Rows: gem types (none, gold, crystal, ruby, pearl) → 5 rows
Columns: bag weight (0kg ~ 7kg) → 8 columns
[0 for _ in range(8)] creates [0,0,0,0,0,0,0,0]금괴는 6kg입니다. 배낭이 6kg 이상이면 넣을 수 있고, 5kg 이하면 넣을 수 없습니다!
금괴(6kg)가 배낭보다 무거우므로, 위 행(없음)의 값을 그대로 복사합니다. 즉 0억.
| 보석\무게 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| 없음 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 금괴 | 0 | 0 | 0 | 0 | 0 | 0 | 13 | 13 |
Gold bar weighs 6kg. If bag can hold 6+ kg → put it in. If 5kg or less → it doesn't fit!
Gold (6kg) is heavier than the bag, so copy the value from the row above (0).
array[row-1][col]max(money[row] + array[row-1][col-weight[row]],array[row-1][col])
수정(4kg)이 배낭보다 무거우므로, 위 행(금괴만)의 값을 그대로 → 0
| 보석\무게 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| 없음 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 금괴 | 0 | 0 | 0 | 0 | 0 | 0 | 13 | 13 |
| 수정 | 0 | 0 | 0 | 0 | 8 | 8 | 13 | 13 |
Crystal (4kg) is heavier, copy row above → 0
루비 6억 + 여유분(0kg)=0억 = 6억 vs 위 행 0억 → 6억
루비 6억 + 여유분 가격 vs 위 행(수정 포함) 8억 → 8억! (수정이 더 좋음)
| 보석\무게 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| 없음 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 금괴 | 0 | 0 | 0 | 0 | 0 | 0 | 13 | 13 |
| 수정 | 0 | 0 | 0 | 0 | 8 | 8 | 13 | 13 |
| 루비 | 0 | 0 | 0 | 6 | 8 | 8 | 13 | 14 |
Ruby 6B + leftover(0kg)=0 = 6B vs above 0B → 6B
1~4kg: 진주(5kg) 안 들어감 → 위 행 복사
5kg: 진주 12억 + 여유분(0kg) 0억 = 12억 vs 위 행 8억 → 12억
6kg: 진주 12억 + 여유분(1kg) 0억 = 12억 vs 위 행 13억 → 13억
7kg: 진주 12억 + 여유분(2kg) 0억 = 12억 vs 위 행 14억 → 14억
| 보석\무게 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| 없음 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 금괴 | 0 | 0 | 0 | 0 | 0 | 0 | 13 | 13 |
| 수정 | 0 | 0 | 0 | 0 | 8 | 8 | 13 | 13 |
| 루비 | 0 | 0 | 0 | 6 | 8 | 8 | 13 | 14 |
| 진주 | 0 | 0 | 0 | 6 | 8 | 12 | 13 | 14 |
1-4kg: Pearl(5kg) doesn't fit → copy row above
5kg: Pearl 12B + leftover(0kg) = 12B vs above 8B → 12B
6kg: Pearl 12B + leftover(1kg) = 12B vs above 13B → 13B
7kg: Pearl 12B + leftover(2kg) = 12B vs above 14B → 14B
The bottom-right cell always contains the optimal answer to the full problem. Each cell builds on previously solved subproblems — that's the beauty of DP!
if weight[row] > col: → copy aboveelse: → max(include, exclude)
| 변수 | 의미 |
|---|---|
weight[row] | 현재 행의 보석 무게 |
col | 현재 열(배낭 무게) |
money[row] | 현재 보석의 가격 |
array[row-1][col] | 이 보석을 안 넣은 경우의 최적값 |
array[row-1][col-weight[row]] | 여유분에 해당하는 이전 최적값 |
| Variable | Meaning |
|---|---|
weight[row] | Weight of current item |
col | Current bag capacity |
money[row] | Value of current item |
value1 | Value if we INCLUDE this item |
value2 | Value if we EXCLUDE this item |
array[row-1][col-weight[row]] looks up the best value for the leftover capacity — and that was already computed! No redundant work.
5행 × 8열의 2차원 배열을 0으로 초기화. 행=보석 개수+1, 열=최대무게+1
0행과 0열은 이미 0이므로, 1부터 시작합니다.
Creates a 5×8 grid of zeros. Rows = gems+1, Cols = maxWeight+1
Outer loop: each gem (row 1 to 4)
Inner loop: each bag capacity (col 1 to 7)
Row 0 and Col 0 are already 0 (base cases).
weight[row] > col → item too heavyweight[row] ≤ col → item can go inCode14-01에서 보석 순서를 진주, 루비, 금괴, 수정으로 변경하여 같은 결과(14억)가 나오는지 확인하세요.
힌트: weight와 money 배열의 순서만 바꾸면 됩니다.
결과는 동일하게 14억! 보석의 순서를 바꿔도 DP는 항상 같은 최적값을 찾습니다.
다음 데이터로 메모이제이션 테이블을 직접 채워보세요.
배낭 최대 무게: 5kg
물건A: 2kg, 3만원 / 물건B: 3kg, 4만원 / 물건C: 4kg, 5만원
| \ | 0 | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|---|
| 없음 | 0 | 0 | 0 | 0 | 0 | 0 |
| A | 0 | 0 | 3 | 3 | 3 | 3 |
| B | 0 | 0 | 3 | 4 | 4 | 7 |
| C | 0 | 0 | 3 | 4 | 5 | 7 |
최적 답: A(2kg)+B(3kg) = 5kg, 7만원!
In Code14-01, change the gem order to Pearl, Ruby, Gold, Crystal. Verify the result is still 14 billion.
Same result: 14 billion! DP finds the optimal value regardless of item order.
Max bag: 5kg. A: 2kg/$3, B: 3kg/$4, C: 4kg/$5. Fill the memo table.
Optimal: A(2kg) + B(3kg) = 5kg, $7!
Note: C alone at 4kg gives $5, but A+B at 5kg gives $7 — DP finds this combination!
5×5 보드게임에서 왼쪽 위에서 출발해 오른쪽 아래까지 이동합니다. 각 칸에 황금이 있고, 오른쪽 또는 아래쪽으로만 이동 가능합니다. 최대 황금을 모으며 도착하세요!
| 1 | 4 | 4 | 2 | 2 |
| 1 | 3 | 3 | 0 | 5 |
| 1 | 2 | 4 | 3 | 0 |
| 3 | 3 | 0 | 4 | 2 |
| 1 | 3 | 4 | 5 | 3 |
In a 5×5 board game, start at the top-left and reach the bottom-right. Each cell has gold. You can only move right (→) or down (↓). Collect the maximum gold!
The maximum gold at any cell = that cell's gold + max(gold from left, gold from above). Each cell's optimal value depends on previously solved cells — perfect for DP!
memo[r][c] = goldMaze[r][c] + max(memo[r][c-1], memo[r-1][c])왼쪽부터 누적합: 1, 1+4=5, 5+4=9, 9+2=11, 11+2=13
위에서부터 누적합: 1, 1+1=2, 2+1=3, 3+3=6, 6+1=7
각 칸 = 현재 황금 + max(왼쪽 메모, 위쪽 메모)
| 1 | 5 | 9 | 11 | 13 |
| 2 | 8 | 12 | 12 | 18 |
| 3 | 10 | 16 | 19 | 19 |
| 6 | 13 | 16 | 23 | 25 |
| 7 | 16 | 20 | 28 | 31 |
Cumulative sum: 1, 5, 9, 11, 13
Cumulative sum: 1, 2, 3, 6, 7
Each cell = current gold + max(left memo, above memo)
최대 황금 31개를 얻을 수 있다는 것은 알았는데, 실제로 어떤 경로로 이동해야 할까요? 도착점에서 출발점으로 거꾸로 추적합니다!
We know the maximum gold is 31, but which path should we take? Trace back from the destination to the start!
피보나치 수열: 1, 1, 2, 3, 5, 8, 13, 21, ...
규칙: F(n) = F(n-1) + F(n-2)
재귀로 풀면? DP로 풀면? 속도가 엄청나게 달라집니다!
Fibonacci: 1, 1, 2, 3, 5, 8, 13, 21, ...
Rule: F(n) = F(n-1) + F(n-2)
Recursive? DP? The speed difference is enormous!
| Method | Answer | Operations |
|---|---|---|
| Recursion | 1,346,269 | 2,692,537 |
| DP | 1,346,269 | 29 |
선생님이 수학 숙제를 내주셨는데, 매번 처음부터 다시 풀어야 한다면? DP는 한 번 풀고 답을 적어두고 다음에 바로 꺼내 씁니다!
F(30)을 구하려면 F(29)+F(28)이 필요하고, F(29)를 구하려면 F(28)+F(27)이 필요하고... F(28)이 두 번 계산됩니다! 이런 중복이 눈덩이처럼 불어납니다.
| n | 재귀 호출 횟수 | DP 계산 횟수 | 배율 |
|---|---|---|---|
| 10 | 177 | 9 | 약 20배 |
| 20 | 21,891 | 19 | 약 1,152배 |
| 30 | 2,692,537 | 29 | 약 92,846배! |
| 40 | 331,160,281 | 39 | 약 849만 배!! |
Imagine if your teacher asked you to solve a math problem, but you had to start from scratch every time? DP solves it once, writes down the answer, and just looks it up next time!
To compute F(30), we need F(29)+F(28). But F(29) also needs F(28)+F(27)... F(28) is computed twice! This snowball effect multiplies exponentially.
| n | Recursive Calls | DP Computations | Ratio |
|---|---|---|---|
| 10 | 177 | 9 | ~20× |
| 20 | 21,891 | 19 | ~1,152× |
| 30 | 2,692,537 | 29 | ~92,846×! |
| 40 | 331,160,281 | 39 | ~8.5 million×!! |
이번에는 각 칸에 압정이 놓여 있습니다. 압정을 최소한으로 밟으며 도착점까지 가야 합니다. 황금 미로와 반대!
힌트: max를 어떤 함수로 바꾸면 될까요?
부등호만 >에서 <로 바꾸면 왼쪽과 위쪽 중 작은 값을 선택하게 됩니다.
최대를 구하던 알고리즘이 부등호 하나로 최소 경로 알고리즘이 됩니다!
This time, each cell has thumbtacks. You need to reach the end stepping on as few as possible. The opposite of the gold maze!
Hint: What should you change max to?
Just changing > to < switches from "maximum gold" to "minimum thumbtacks"!
Result: 19 thumbtacks
제한된 용량에서 최대 가치 조합 찾기
그래프에서 최적 경로 탐색
중복 계산 제거로 효율화
두 문자열의 유사도 측정
Find max value within weight limit
Find optimal routes in graphs
Eliminate redundant computation
Measure string similarity
| 개념 | 설명 |
|---|---|
| 동적 계획법 | 큰 문제를 작은 문제로 나누고 결과를 저장하는 알고리즘 |
| 메모이제이션 | 한 번 계산한 결과를 표에 저장해 재사용 |
| 점화식 | 작은 문제의 답으로 큰 문제를 푸는 규칙 |
| 배낭 문제 | 무게 제한 내 최대 가치 조합 찾기 |
| 황금 미로 | 최대/최소 경로 합계 찾기 |
| 방법 | 정확성 | 속도 | 특징 |
|---|---|---|---|
| 브루트 포스 | O | O(2n) | 모든 경우 시도 |
| 탐욕 | △ | O(n log n) | 눈앞의 최선 |
| DP | O | O(n×W) | 메모이제이션 |
| Concept | Description |
|---|---|
| DP | Divide + Store results = No redundant work |
| Memoization | Save computed results in a table for reuse |
| Recurrence | Rule linking small answers to big answers |
| Knapsack | Max value within weight limit |
| Gold Maze | Max/min path sum in a grid |
| Method | Accuracy | Speed | Trait |
|---|---|---|---|
| Brute Force | Always | O(2n) | Try everything |
| Greedy | Sometimes | O(n log n) | Local best |
| DP | Always | O(n×W) | Memoization |
배낭 최대 무게가 6kg이고, 보석이 다음과 같을 때 최대 가격은?
다이아: 3kg, 10억 / 에메랄드: 2kg, 7억 / 사파이어: 4kg, 9억
| \ | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|---|
| 없음 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 다이아 | 0 | 0 | 0 | 10 | 10 | 10 | 10 |
| 에메랄드 | 0 | 0 | 7 | 10 | 10 | 17 | 17 |
| 사파이어 | 0 | 0 | 7 | 10 | 10 | 17 | 17 |
최대 가격: 17억! 다이아(3kg, 10억) + 에메랄드(2kg, 7억) = 5kg
다음 3×3 미로에서 최대 황금은?
| 2 | 3 | 1 |
| 1 | 5 | 2 |
| 4 | 2 | 1 |
| 2 | 5 | 6 |
| 3 | 10 | 12 |
| 7 | 12 | 13 |
최대 황금: 13개! 경로: 2→3→5→2→1 또는 2→3→5→2→1
F(20)을 재귀로 구할 때 함수 호출 횟수는 약 몇 번인가?
약 21,891번!
재귀는 O(2n)이므로 약 220 ≈ 100만에 가까운 호출이 일어나지만, 실제로는 트리 구조 때문에 약 21,891번입니다. DP라면 단 19번이면 충분합니다.
Max weight 6kg. Diamond: 3kg/10B, Emerald: 2kg/7B, Sapphire: 4kg/9B. Maximum value?
Max value: 17 billion!
Diamond(3kg) + Emerald(2kg) = 5kg, 17B
Find the maximum gold in a 3×3 maze: [[2,3,1],[1,5,2],[4,2,1]]
Memo table: [[2,5,6],[3,10,12],[7,12,13]]
Maximum gold: 13!
How many function calls does recursive Fibonacci need for F(20)?
About 21,891 calls!
DP needs only 19 computations. That's a 1,152× difference!