๋์ ํ๋ก๊ทธ๋๋ฐ(Dynamic Programming)์ด๋?
๋์ ํ๋ก๊ทธ๋๋ฐ(DP)์ ์์ ๋ฌธ์ ๋ค์ ํด๋ฅผ ํ์ฉํ์ฌ ๋ ํฐ ๋ฌธ์ ์ ํด๋ฅผ ๊ตฌํ๋ ์๊ณ ๋ฆฌ์ฆ ๊ธฐ๋ฒ ์ด๋ค. ์ผ๋ฐ์ ์ผ๋ก ๋ฌธ์ ๋ฅผ ์ฌ๋ฌ ์์ ๋ถ๋ถ ๋ฌธ์ ๋ก ๋๋๊ณ , ์ค๋ณต ๊ณ์ฐ์ ์ค์ด๊ธฐ ์ํด ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅ(memoization) ํ๋ ๋ฐฉ์์ผ๋ก ์ฌ์ฉ๋๋ค.
๋์ ํ๋ก๊ทธ๋๋ฐ์ด ํจ๊ณผ์ ์ธ ๊ฒฝ์ฐ:
- ์ต์ ๋ถ๋ถ ๊ตฌ์กฐ(Optimal Substructure): ํฐ ๋ฌธ์ ์ ์ต์ ํด๊ฐ ์์ ๋ถ๋ถ ๋ฌธ์ ์ ์ต์ ํด๋ก ๊ตฌ์ฑ๋ ์ ์์
- ์ค๋ณต ๋ถ๋ถ ๋ฌธ์ (Overlapping Subproblems): ๋์ผํ ์์ ๋ฌธ์ ๋ฅผ ์ฌ๋ฌ ๋ฒ ํด๊ฒฐํด์ผ ํ๋ ๊ฒฝ์ฐ
๋ํ์ ์ธ DP ๋ฌธ์ :
- ์ต๋จ ๊ฒฝ๋ก ๋ฌธ์ (Floyd-Warshall, Bellman-Ford)
- ๋ฐฐ๋ญ ๋ฌธ์ (Knapsack Problem)
- ๋์ ๊ฑฐ์ค๋ฆ๋ ๋ฌธ์ (Coin Change Problem)
- ๊ณ๋จ ์ค๋ฅด๊ธฐ ๋ฌธ์ (Climbing Stairs)
- ์ต์ฅ ๊ณตํต ๋ถ๋ถ ์์ด (LCS, Longest Common Subsequence)
1. ๋์ ๊ฑฐ์ค๋ฆ๋ ๋ฌธ์ (Coin Change Problem)
๋ฌธ์ ์ค๋ช
์ฃผ์ด์ง ๋์ ์ธํธ์์ ํน์ ๊ธ์ก์ ๋ง๋ค๊ธฐ ์ํ ์ต์ ๋์ ๊ฐ์๋ฅผ ์ฐพ๋ ๋ฌธ์ ์ด๋ค. ํ์์ ์๊ณ ๋ฆฌ์ฆ(Greedy Algorithm) ์ ํญ์ ์ต์ ํด๋ฅผ ๋ณด์ฅํ์ง ์๊ธฐ ๋๋ฌธ์, DP๋ฅผ ํ์ฉํ์ฌ ์ต์ ํด๋ฅผ ์ฐพ๋๋ค.
JavaScript ์ฝ๋:
function coinChange(coins, amount) {
let dp = new Array(amount + 1).fill(Infinity);
dp[0] = 0;
for (let coin of coins) {
for (let j = coin; j <= amount; j++) {
dp[j] = Math.min(dp[j], dp[j - coin] + 1);
}
}
return dp[amount] === Infinity ? -1 : dp[amount];
}
์๊ฐ ๋ณต์ก๋: O(n × k) (n: ๋์ ๊ฐ์, k: ๋ชฉํ ๊ธ์ก)
๊ณต๊ฐ ๋ณต์ก๋: O(k)
2. ๊ฐ๊ตฌ๋ฆฌ ์ ํ ๋ฌธ์ (Frog Jump Problem)
๋ฌธ์ ์ค๋ช
๊ฐ๊ตฌ๋ฆฌ๊ฐ ์์น 0์์ k๊น์ง ์ด๋ํ๊ณ ์ถ๋ค. ๊ฐ๊ตฌ๋ฆฌ๋ ์ ํด์ง n๊ฐ์ ์ ํ ๊ฑฐ๋ฆฌ ๋ฅผ ๊ฐ์ง ์ ์์ผ๋ฉฐ, ์ ํ๋ฅผ ์กฐํฉํ์ฌ k์ ๋๋ฌํ๋ ์๋ก ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์๋ฅผ ๊ตฌํ๋ ๋ฌธ์ ์ด๋ค.
JavaScript ์ฝ๋:
function frogJump(S, k, q) {
let dp = new Array(k + 1).fill(0);
dp[0] = 1;
for (let j = 1; j <= k; j++) {
for (let s of S) {
if (s <= j) {
dp[j] = (dp[j] + dp[j - s]) % q;
}
}
}
return dp[k];
}
์๊ฐ ๋ณต์ก๋: O(n × k) (๋ชจ๋ j์ ๋ํด n๊ฐ์ ์ ํ ๊ฑฐ๋ฆฌ ํ์)
๊ณต๊ฐ ๋ณต์ก๋: O(k) (1์ฐจ์ ๋ฐฐ์ด ์ฌ์ฉ)
3. DP์ ๋ฉ๋ชจ๋ฆฌ ์ต์ ํ
์ ๋ฌธ์ ์์ 2์ฐจ์ ๋ฐฐ์ด์ด ์๋๋ผ 1์ฐจ์ ๋ฐฐ์ด์ ์ฌ์ฉํ์ฌ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ต์ ํ ํ ์ ์๋ค. ๊ธฐ์กด์ 2์ฐจ์ dp[i][j] ๋ฐฐ์ด ๋์ dp[j]๋ง ์ ์งํ๋ฉด ๋๋ค.
JavaScript ์ฝ๋:
function optimizedCoinChange(coins, amount) {
let dp = new Array(amount + 1).fill(Infinity);
dp[0] = 0;
for (let coin of coins) {
for (let j = coin; j <= amount; j++) {
dp[j] = Math.min(dp[j], dp[j - coin] + 1);
}
}
return dp[amount] === Infinity ? -1 : dp[amount];
}
์ด๋ฌํ ์ต์ ํ๋ฅผ ํตํด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ O(k)๋ก ์ค์ผ ์ ์๋ค.
๋๊ธ