Search
Duplicate
πŸ“—

Dynamic Programming

DPλž€?

GeeksforGeeks에 μ˜ν•˜λ©΄ DPλŠ” Sub-Problemλ“€λ‘œ λ‚˜λˆ„μ–΄ κ²°κ³Ό 값을 μ €μž₯ν•¨μœΌλ‘œμ¨ 계산 수λ₯Ό μ€„μ΄λŠ” 것을 λ§ν•œλ‹€.
κ·ΈλŸ¬λ‚˜ μœ„λŠ” κ·Έμ € μ •μ˜μ΄κ³  μ‹€μ œλ‘œ ν’€ λ•ŒλŠ” λ‹€μŒκ³Ό 같은 μ ‘κ·Ό 방법이 νŽΈν•  것이닀. DPλŠ” λ¬Έμ œλ“€μ„ μž‘μ€ Sub-Problem으둜 μͺΌκ°œμ–΄ Sub-Problem κ°„μ˜ 상관 관계에 μ§‘μ€‘ν•˜μ—¬ 결과적으둜 전체 Problem을 ν‘ΈλŠ” 방법이닀.
쑰금 더 μΉœκ·Όν•˜κ²Œ λ§ν•˜κΈ° μœ„ν•΄ 계단에 λΉ„μœ ν•΄ 보겠닀. μš°λ¦¬κ°€Β nn번째 계단을 밟기 μœ„ν•΄μ„œλŠ”Β nβˆ’1,nβˆ’2,nβˆ’3,...,1n-1, n-2, n-3, ..., 1번째 계단듀을 λ°Ÿμ•„μ•Ό ν•œλ‹€. μˆœμ„œλŒ€λ‘œ 계단을 λ°ŸλŠ”λ‹€λ©΄ 끝에 도달할 수 μžˆλ‹€. λ¬Έμ œκ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ κ³„λ‹¨μœΌλ‘œ λ°”κΎΈμ–΄ 생각해 보도둝 ν•œλ‹€. μ–΄λ– ν•œ μƒνƒœμ—μ„œ λ‹€μŒ μƒνƒœλ‘œ λ‚˜μ•„κ°€κΈ° μœ„ν•΄ 무슨 일을 ν•΄μ•Όν•˜λŠ”μ§€ κ³ λ―Όν•˜κ³  처음 μƒνƒœμ™€ 끝 μƒνƒœλ₯Ό κ³ λ €ν•˜λ©΄ λ¬Έμ œλŠ” ν’€λ¦°λ‹€.
ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ„ 예둜 λ“€μ–΄λ³΄μž.
fn=fnβˆ’1+fnβˆ’1f_n = f_{n-1} + f_{n-1}
f10f_{10}을 κ³„μ‚°ν•˜κΈ° μœ„ν•΄μ„œ μž¬κ·€ ν•¨μˆ˜λ₯Ό μ΄μš©ν•œλ‹€λ©΄ f10f_{10}을 계산할 λ•Œ f5f_5κ°€ ν•„μš”ν•  λ•Œλ§ˆλ‹€, f4,f3,f2,f1,f0f_4, f_3, f_2, f_1, f_0을 계산해야 ν•œλ‹€. μ΄λ ‡κ²Œ ν‘Όλ‹€λ©΄ ꡉμž₯히 λΉ„νš¨μœ¨μ μ΄μ§€ μ•Šμ€κ°€? 이 방법 λŒ€μ‹ μ—, 이전 두 값을 μ•Œ λ•Œ λ‹€μŒ 값을 μ•Œ 수 μžˆλ‹€λŠ” 점을 κ³ λ €ν•˜μ—¬ f2,f3,f4...f_2, f_3, f_4 ... μˆœμ„œλ‘œ 계산해 λ‚˜κ°„λ‹€λ©΄ μ‰½κ²Œ ν’€ 수 μžˆλ‹€λŠ” 것을 μœ μΆ”ν•  수 μžˆλ‹€.
이처럼 μž„μ˜μ˜ nn번째 Sub-Problem에 λŒ€ν•˜μ—¬, n+1n+1 번째 Sub-Problem을 ꡬ할 수 μžˆλ‹€λ©΄ DP둜 ν’€ 수 μžˆλ‹€. λ˜ν•œ 이 λ•Œ λ°˜λ“œμ‹œ 처음 Sub-Problemκ³Ό λ§ˆμ§€λ§‰ Sub-Problem을 κ³ λ €ν•΄μ•Ό ν•œλ‹€. 경계 κ°’μ—μ„œ ν”„λ‘œκ·Έλž¨μ΄ 버그λ₯Ό μΌμœΌν‚¬ κ°€λŠ₯성이 λ†’κΈ° λ•Œλ¬Έμ΄λ‹€. λ‚˜μ€‘μ— 문제의 λ‚œμ΄λ„κ°€ 쑰금 더 μƒμŠΉν•œλ‹€λ©΄, μž„μ˜μ˜ (n,m)(n,m) Sub-Problem에 λŒ€ν•˜μ—¬ (n+1,m)(n+1, m)κ³Ό (n,m+1)(n, m+1) 번째 Sub-Problem을 ꡬ할 수 μžˆμ„ λ•Œ 2차원 DP도 ν’€ 수 μžˆλ‹€. DP의 원리λ₯Ό 잘 νŒŒμ•…ν•œλ‹€λ©΄ 보닀 μ–΄λ €μš΄ 3, 4원 DP λ¬Έμ œλ“€λ„ ν’€ 수 μžˆμ„ 것이닀. (γ…‹γ…‹γ…‹γ…‹γ…‹γ…‹..)
λŒ€λΆ€λΆ„ 눈치λ₯Ό μ±˜κ² μ§€λ§Œ, μ ν™”μ‹μœΌλ‘œ λ‚˜νƒ€λ‚Ό 수 μžˆλŠ” λͺ¨λ“  μˆ˜μ—΄μ€ DP둜 ν’€ 수 μžˆλ‹€. ν•˜μ§€λ§Œ 이 말이 곧 μ ν™”μ‹μœΌλ‘œ λ‚˜νƒ€λ‚Ό 수 μžˆλ‹€λ©΄ 무쑰건 DP둜 ν’€μ–΄μ•Ό ν•œλ‹€λŠ” 것은 μ•„λ‹ˆλ‹€. λ°˜λ‘€λ‘œ ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ„ κ΅¬ν•˜λŠ” O(logn)의 μ‹œκ°„ λ³΅μž‘λ„λ₯Ό κ°€μ§€λŠ” DPκ°€ μ•„λ‹Œ μ•Œκ³ λ¦¬μ¦˜μ΄ μžˆλ‹€.

주둜 λ‚˜μ˜€λŠ” 문제?

μ½”λ”© ν…ŒμŠ€νŠΈμ— 자주 λ‚˜μ˜€λŠ” DP λ¬Έμ œλ“€μ€ 경우의 수λ₯Ό νŒŒμ•…ν•˜λŠ” 문제, 쑰합을 κ΅¬ν•˜λŠ” 문제, LIS (Longest Increasing Subsequence) μ •λ„λ‘œ μš”μ•½ν•  수 μžˆλ‹€.
β€’
경우의 수λ₯Ό νŒŒμ•…ν•˜λŠ” 문제
보톡 기초적인 λ¬Έμ œλ“€μ΄ 많고 Sub-Problem으둜 λ‚˜λˆ„λŠ” κ²ƒλ§Œ μƒκ°ν•˜λ©΄ μ‰½κ²Œ ν’€ 수 μžˆλ‹€.
β€’
쑰합을 κ΅¬ν•˜λŠ” 문제
μ‘°ν•©μ˜ 곡식은 λ‹€μŒκ³Ό κ°™λ‹€.
nCr=n!r!(nβˆ’r)!nCr = \frac{n!}{r!(n-r)!}
이λ₯Ό κ³΅μ‹λŒ€λ‘œ νŒ©ν† λ¦¬μ–Όμ„ μ΄μš©ν•΄μ„œ ν’€λ©΄ 맀우 λΉ λ₯΄κ²Œ Overflowκ°€ λ‚˜μ™€μ„œ 잘λͺ»λœ 값을 μ–»κ²Œ λœλ‹€. 쑰합에 λŒ€ν•œ 곡식은 μœ„μ˜ 것 말고 ν•œ 가지가 더 μžˆλ‹€. 이 곡식을 ν™œμš©ν•˜λ©΄, 쀑간 계산 κ³Όμ •μ—μ„œ 더 큰 값이 λ“±μž₯ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— Overflowλ₯Ό ν”Όν•  수 μžˆλ‹€.
nCr=nβˆ’1Crβˆ’1+nβˆ’1Cr_nC_r = _{n-1}C_{r-1} + _{n-1}C_r
파슀칼의 μ‚Όκ°ν˜•μ€ μœ„ 곡식을 μ‹œκ°μ μœΌλ‘œ λ³Ό 수 μžˆλŠ” μ‚Όκ°ν˜•μ΄λ‹€. 파슀칼의 μ‚Όκ°ν˜•μ€ μ•„λž˜μ™€ κ°™λ‹€.
파슀칼의 μ‚Όκ°ν˜•μ„ 잘 생각해보면, nn번째 쀄을 μ•Œλ©΄ n+1n+1번째 쀄을 μ•Œ 수 있고 쀑간 계산 κ³Όμ •μ—μ„œ μ΅œμ’… 결과보닀 큰 값이 λ‚˜μ˜€μ§€ μ•ŠλŠ” 것을 μ•Œ 수 μžˆλ‹€. λ”°λΌμ„œ μ΅œμ’… κ²°κ³Ό 값이 Overflowκ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ” 값이라면, 이 방법을 ν†΅ν•΄μ„œ 문제 없이 정닡을 ꡬ할 수 μžˆλŠ” 것을 μ•Œ 수 μžˆλ‹€. λŒ€λΆ€λΆ„μ˜ μ‘°ν•© λ¬Έμ œλŠ” 주어진 λ¬Έμ œκ°€ 쑰합을 κ΅¬ν•΄μ•Όν•˜λŠ” λ¬Έμ œμΈμ§€ νŒŒμ•…λ§Œ ν•˜λ©΄ μ‰½κ²Œ ν’€ 수 μžˆλ‹€.
β€’
LIS (Longest Increasing Subsequence)
LISλŠ” Longest Increasing Subsequence의 μ•½μžλ‘œ 주어진 μˆ˜μ—΄μ˜ 졜μž₯ λΆ€λΆ„ μˆ˜μ—΄μ„ κ΅¬ν•˜λŠ” λ¬Έμ œμ΄λ‹€. LISλ₯Ό κ΅¬ν•˜λŠ” 유λͺ…ν•œ λ°©λ²•μœΌλ‘œλŠ” 이뢄 νƒμƒ‰μœΌλ‘œ O(nlogn)λ§Œμ— κ΅¬ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜λ„ μžˆμ§€λ§Œ, DPλ₯Ό ν†΅ν•΄μ„œλ„ ν’€ 수 μžˆλ‹€.
DPλ₯Ό ν†΅ν•΄μ„œ LISλ₯Ό ν‘ΈλŠ” 방법은 μˆ˜μ—΄μ˜ μ›μ†Œλ₯Ό ν•˜λ‚˜μ”© λ³΄λ©΄μ„œ ν•΄λ‹Ή μ›μ†Œλ‘œ λλ‚˜λŠ” LIS의 길이λ₯Ό μΆ”μ ν•˜λ©΄ LISλ₯Ό ꡬ할 수 μžˆλ‹€. μž„μ˜μ˜ μ›μ†Œλ‘œ λλ‚˜λŠ” LISλ₯Ό κ΅¬ν•˜κΈ° μœ„ν•΄μ„  μžκΈ°λ³΄λ‹€ μ•žμ„œλ©΄μ„œ μžκΈ°λ³΄λ‹€ μž‘μ€ μ›μ†Œλ‘œ λλ‚˜λŠ” LIS 쀑 κ°€μž₯ κΈ΄ LISλ₯Ό μ°Ύμ•„μ•Ό ν•œλ‹€. κ·Έ λ•Œ 찾은 LIS 뒀에 ν•΄λ‹Ή μ›μ†Œλ₯Ό λ”ν•˜λ©΄ 그게 ν•΄λ‹Ή μ›μ†Œλ‘œ λλ‚˜λŠ” LIS 이기 λ•Œλ¬Έμ΄λ‹€.
예λ₯Ό λ“€μ–΄λ³΄μž.
1,6,2,5,7,3,5,71, 6,2,5,7,3,5,7
제일 μ•žμ— μžˆλŠ” 11의 경우 μžμ‹ λ³΄λ‹€ μ•žμ„  μ›μ†Œκ°€ μ—†κΈ° λ•Œλ¬Έμ— 첫 번째 μ›μ†Œλ‘œ λλ‚˜λŠ” LISλŠ” 11이닀.
κ·Έ λ‹€μŒ μ›μ†ŒμΈ 66을 보면 μžμ‹ λ³΄λ‹€ μ•žμ„œλ©΄μ„œ μžμ‹ λ³΄λ‹€ μž‘μ€ μ›μ†ŒλŠ” 11둜 1κ°œκ°€ μžˆλ‹€. λ”°λΌμ„œ 66으둜 λλ‚˜λŠ” LISλŠ” 1,61,6이 λœλ‹€.
κ·Έ λ‹€μŒ μ›μ†ŒμΈ 22λ₯Ό 보면 μžμ‹ λ³΄λ‹€ μ•žμ„œλ©΄μ„œ μžμ‹ λ³΄λ‹€ μž‘μ€ μ›μ†ŒλŠ” 11둜 1κ°œκ°€ μžˆλ‹€. λ”°λΌμ„œ 22둜 λλ‚˜λŠ” LISλŠ” 1,21, 2κ°€ λœλ‹€.
κ·Έ λ‹€μŒ μ›μ†ŒμΈ 55λ₯Ό 보면 μžμ‹ λ³΄λ‹€ μ•žμ„œλ©΄μ„œ μžμ‹ λ³΄λ‹€ μž‘μ€ μ›μ†ŒλŠ” 11κ³Ό 22κ°€ μžˆλ‹€. 이 λ•Œ, 11둜 λλ‚˜λŠ” LISλŠ” 11이고, 22둜 λλ‚˜λŠ” LISλŠ” 1,21,2이닀. λ”°λΌμ„œ 보닀 κΈ΄ 1,21, 2λ₯Ό λΆ™μ—¬μ„œ 55둜 λλ‚˜λŠ” LISλŠ” 1,2,51,2,5κ°€ λœλ‹€.
이처럼 각 μ›μ†Œλ§ˆλ‹€ ν•΄λ‹Ή μ›μ†Œλ‘œ λλ‚˜λŠ” LISλ₯Ό μΆ”μ ν•œ 후에 κ·Έ μ€‘μ—μ„œ κ°€μž₯ κΈ΄ LISλ₯Ό 찾으면 문제λ₯Ό ν•΄κ²°ν•  수 μžˆλ‹€.

λ©”λͺ¨μ΄μ œμ΄μ…˜ (Memoization)

λ©”λͺ¨μ΄μ œμ΄μ…˜μ€ 쀑볡 계산을 ν”Όν•˜λŠ” 계산 μ΅œμ ν™” 기법을 λ§ν•œλ‹€. DP 문제λ₯Ό 풀닀보면 같은 값을 계속 ν˜ΈμΆœν•˜λŠ” κ²½μš°κ°€ λ§Žλ‹€. μ§€κΈˆμ€ ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ„ κ³„μ†ν•΄μ„œ 계산해야 ν•œλ‹€κ³  κ°€μ •ν•΄λ³΄μž. μ²˜μŒμ— f100f_{100}의 값이 ν•„μš”ν•˜κ³ , κ·Έ 직후에 f50f_{50} 값이 ν•„μš”ν•˜λ‹€λ©΄ 이 두 값을 κ³„μ‚°ν•˜κΈ° μœ„ν•΄μ„œ ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄ 계산을 λ”°λ‘œ λ”°λ‘œ ν•  ν•„μš”κ°€ μ—†λ‹€λŠ” 것이닀. ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ„ DP λ°©μ‹μœΌλ‘œ κ³„μ‚°ν–ˆλ‹€κ³  κ°€μ •ν•  λ•Œ, f100f_{100}을 κ³„μ‚°ν•˜λŠ” κ³Όμ •μ—μ„œ f0f_0λΆ€ν„° f99f_{99}κΉŒμ§€ κ³„μ‚°ν•˜κ²Œ λœλ‹€. f100f_{100}을 κ³„μ‚°ν•˜λŠ” λ™μ•ˆ κ·Έ μ „ 값듀을 배열에 μ €μž₯ν•œλ‹€λ©΄, f50f_{50}을 λ‹€μ‹œ 계산할 ν•„μš” 없이 λ°”λ‘œ 값을 ꡬ할 수 μžˆλ‹€. λ©”λͺ¨μ΄μ œμ΄μ…˜μ€ νŠΉλ³„νžˆ 어렡지도 μ•Šκ³  DP 외에도 많이 μ‚¬μš©λ˜λ‹ˆ 이 κ°œλ…μ„ μ΅ν˜€λ‘λ©΄ μ’‹λ‹€.