contents
๐ ์ฝ๋ฉ ํ ์คํธ๋ฅผ ์ํ ๋์ ํ๋ก๊ทธ๋๋ฐ(DP) ๊ฐ์ด๋
๋ค์์ DP์ ํต์ฌ ๊ฐ๋ , ์ ํ, ๊ตฌํ ์ ๋ต, ๊ทธ๋ฆฌ๊ณ Java ์คํ์ผ์ ์์ ์ฝ๋๋ฅผ ํฌํจํ ์์ธ ์ค๋ช ์ ๋๋ค.
1. ๋์ ํ๋ก๊ทธ๋๋ฐ(DP)์ด๋?
๋์ ํ๋ก๊ทธ๋๋ฐ(Dynamic Programming)์ ํฐ ๋ฌธ์ ๋ฅผ ์์ ํ์ ๋ฌธ์ ๋ก ๋๋๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ์ฌ ์ฌ์ฌ์ฉํจ์ผ๋ก์จ ๋ถํ์ํ ์ค๋ณต ๊ณ์ฐ์ ํผํ๊ณ ํจ์จ์ ์ผ๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ๋๋ค.
- ํต์ฌ ์์ด๋์ด:
- ์ค๋ณต๋๋ ํ์ ๋ฌธ์ (Overlapping Subproblems)
- ์ต์ ๋ถ๋ถ ๊ตฌ์กฐ(Optimal Substructure)
- ์ข
๋ฅ:
- Top-down (๋ฉ๋ชจ์ด์ ์ด์ ): ์ฌ๊ท + ์บ์ฑ
- Bottom-up (ํญ๋ฉ์ด์ ์ด์ ): ๋ฐ๋ณต๋ฌธ์ผ๋ก dp ํ ์ด๋ธ ์ฑ์ฐ๊ธฐ
- ์์ ํ์์ด ์ง์ ์๊ฐ๋ณต์ก๋๋ฅผ ๊ฐ์ง๋ ๊ฒฝ์ฐ์๋ DP๋ฅผ ์ฌ์ฉํ๋ฉด ๋คํญ ์๊ฐ์ผ๋ก ์ค์ผ ์ ์์ต๋๋ค.
2. DP ํจํด & ์์
a. ํผ๋ณด๋์น ์์ด
์ฌ๊ท (๋นํจ์จ์ )
int fib(int n) {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
}
DP (Top-down + ๋ฉ๋ชจ์ด์ ์ด์ )
int[] memo = new int[n+1];
int fib(int n) {
if (n <= 1) return n;
if (memo[n] != 0) return memo[n];
return memo[n] = fib(n - 1) + fib(n - 2);
}
DP (Bottom-up)
int fib(int n) {
if (n <= 1) return n;
int[] dp = new int[n+1];
dp[0] = 0; dp[1] = 1;
for (int i = 2; i <= n; i++)
dp[i] = dp[i-1] + dp[i-2];
return dp[n];
}
b. 0/1 ๋ฐฐ๋ญ ๋ฌธ์ (Knapsack)
๋ฌธ์ :
๊ฐ๊ธฐ ๋ค๋ฅธ ๋ฌด๊ฒ์ ๊ฐ์น๋ฅผ ๊ฐ์ง n๊ฐ์ ์์ดํ
์ด ์ฃผ์ด์ง ๋, ๋ฐฐ๋ญ ๋ฌด๊ฒ ์ ํ W ์์์ ์ต๋ ๊ฐ์น๋ฅผ ๊ตฌํ์ธ์.
int knapsackDP(int[] w, int[] v, int W) {
int n = w.length;
int[][] dp = new int[n+1][W+1];
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= W; j++) {
if (w[i-1] <= j)
dp[i][j] = Math.max(dp[i-1][j],
dp[i-1][j-w[i-1]] + v[i-1]);
else
dp[i][j] = dp[i-1][j];
}
}
return dp[n][W];
}
dp[i][j]: ์ฒ์ i๊ฐ์ ์์ดํ ์ ๊ณ ๋ คํ์ ๋, ๋ฌด๊ฒ ํ๋ j์์์ ์ต๋ ๊ฐ์น
c. ์ต์ฅ ์ฆ๊ฐ ๋ถ๋ถ์์ด (LIS)
int lengthOfLIS(int[] nums) {
int n = nums.length, max = 1;
int[] dp = new int[n];
Arrays.fill(dp, 1);
for (int i = 1; i < n; i++)
for (int j = 0; j < i; j++)
if (nums[i] > nums[j])
dp[i] = Math.max(dp[i], dp[j] + 1);
for (int val : dp) max = Math.max(max, val);
return max;
}
- dp[i]: i๋ฒ์งธ ์์๋ก ๋๋๋ LIS์ ๊ธธ์ด
d. ํธ์ง ๊ฑฐ๋ฆฌ(Edit Distance)
int editDistance(String a, String b) {
int[][] dp = new int[a.length()+1][b.length()+1];
for (int i = 0; i <= a.length(); i++)
for (int j = 0; j <= b.length(); j++) {
if (i == 0) dp[i][j] = j;
else if (j == 0) dp[i][j] = i;
else if (a.charAt(i-1) == b.charAt(j-1))
dp[i][j] = dp[i-1][j-1];
else
dp[i][j] = 1 + Math.min(dp[i-1][j-1],
Math.min(dp[i-1][j], dp[i][j-1]));
}
return dp[a.length()][b.length()];
}
- dp
[i][j]: a์ ์ฒ์ i๊ฐ ๋ฌธ์๋ฅผ b์ ์ฒ์ j๊ฐ ๋ฌธ์๋ก ๋ฐ๊พธ๋๋ฐ ํ์ํ ์ต์ ์ฐ์ฐ ์
e. ๋์ ๊ตํ (Coin Change)
int coinChange(int[] coins, int amount) {
int[] dp = new int[amount+1];
Arrays.fill(dp, amount+1);
dp[0] = 0;
for (int coin : coins)
for (int i = coin; i <= amount; i++)
dp[i] = Math.min(dp[i], dp[i-coin] + 1);
return dp[amount] > amount ? -1 : dp[amount];
}
- dp[i]: i์์ ๋ง๋ค๊ธฐ ์ํด ํ์ํ ์ต์ ๋์ ๊ฐ์
3. DP ๋ฌธ์ ์ ํ๋ณ ๋ถ๋ฅ
| ์ ํ | ์์ ๋ฌธ์ | ์ํ ์ ์ ์ |
|---|---|---|
| ๋ถ๋ถ์์ด/๋ถ๋ถ๋ฐฐ์ด | LIS, LCS | dp[i], dp[i][j] |
| ๊ฒฉ์/2D ๊ฒฝ๋ก | Unique Paths, ์ต์ ๊ฒฝ๋ก ํฉ | dp[i][j] |
| ๋ถ๋ถ์งํฉ/Partition | Knapsack, Target Sum | dp[i][j] ๊ฐ๋ฅ ์ฌ๋ถ |
| ๋ฌธ์์ด ๋ณํ | Edit Distance, Palindrome | dp[i][j] |
| ๊ฒฝ์ฐ์ ์ ๊ณ์ฐ | Coin Change, Climb Stairs | dp[i] = ๊ฒฝ์ฐ์ ์ |
4. DP ๊ตฌํ ๋จ๊ณ
- ์ํ ์ ์ (State)
- ๋ฌธ์ ๋ฅผ ๋ ์์ ํ์ ๋ฌธ์ ๋ก ์ ์
- ๊ธฐ์ ์กฐ๊ฑด (Base case)
- ๊ฐ์ฅ ์์ ๊ฐ์ ํด๋ฅผ ๋ฏธ๋ฆฌ ์ ์
- ์ ํ์ (Recurrence Relation)
- ํฐ ๋ฌธ์ ๋ฅผ ์์ ๋ฌธ์ ์ ํด๋ก๋ถํฐ ๋ง๋๋ ๋ฐฉ๋ฒ
- ๊ณ์ฐ ์์ (Iteration Order)
- Bottom-up ๋๋ Top-down
- ์ต์ ํ (Optimization)
- ๊ณต๊ฐ ์ต์ ํ(1D ๋ฐฐ์ด), ๋ถํ์ํ ๊ณ์ฐ ์ค์ด๊ธฐ
5. ์ค์ ํ
- ๋ฌธ์ ์์ "์ต๋", "์ต์", "๊ฒฝ์ฐ์ ์" ๋ฑ์ด ๋์ค๋ฉด DP๋ฅผ ์์ฌ
- Top-down: ์์ฑํ๊ธฐ ์ฌ์, ์ดํด ์ง๊ด์
Bottom-up: ๋ฉ๋ชจ๋ฆฌ ์์ธก ๊ฐ๋ฅ, ๋ฐ๋ณต๋ฌธ - dp ํ ์ด๋ธ ์ํ๋ฅผ ์ถ๋ ฅํด์ ๋๋ฒ๊น
- ๋ฌธ์์ด/๊ฒฉ์: 2D ๋ฐฐ์ด, ์์ด/์ซ์: 1D ๋ฐฐ์ด ๋ง์ด ์ฌ์ฉ
6. ๊ณ ๊ธ ๊ฐ๋
- ์ํ ์์ถ(State Compression): ๋นํธ๋ง์คํฌ ๋ฑ์ ์ฌ์ฉํด ๊ณต๊ฐ ์ ์ฝ
- ๋ค์ฐจ์ DP:
dp[i][j][k]โฆํํ, ์ ์ฝ ์กฐ๊ฑด ์ถ๊ฐ - ํธ๋ฆฌ/๊ทธ๋ํ DP: DFS + DP ๊ฒฐํฉ
- DP + ๋ฐฑํธ๋ํน: ์ต์ ํด ๋ฟ ์๋๋ผ ํด์ ๋ชฉ๋ก๋ ์์ฑ
7. ์์ฝ ํ ์ด๋ธ
| ๋ฌธ์ ์ ํ | DP ์ํ ์ | ์ ํ์ ์์ |
|---|---|---|
| ํผ๋ณด๋์น | dp[n] | dp[n-1] + dp[n-2] |
| LIS | dp[i] | max(dp[j]+1) if a[i]>a[j] |
| Edit Distance | dp[i][j] | dp[i-1][j-1], dp[i][j-1]โฆ |
| Coin Change | dp[amount] | min(dp[amount-coin]+1) |
| Knapsack | dp[i][w] | max(์ด์ ๊ฐ, ์ด์ +value) |
references