DP(Dynamic Programming)

๋ž€?

๋ณต์žกํ•œ ๋ฌธ์ œ๋ฅผ ์ž‘์€ ํ•˜์œ„ ๋ฌธ์ œ๋กœ ๋‚˜๋ˆ„์–ด ํ‘ธ๋Š” ์•Œ๊ดด์ฆ˜ ์„ค๊ณ„ ๊ธฐ๋ฒ• ์ž„. ์ฃผ๋กœ ์ค‘๋ณต๋˜๋Š” ํ•˜์œ„ ๋ฌธ์ œ(Subproblems) ๊ฐ€ ์žˆ๊ณ , ์ด๋“ค์„ ํ•œ ๋ฒˆ๋งŒ ๊ณ„์‚ฐํ•˜๊ณ  ๊ทธ ๊ฐ’์„ ์žฌ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ์„ ๋•Œ ๋งค์šฐ ํšจ์œจ์ ์œผ๋กœ ์ž‘๋™ํ•จ.


1. DP ์˜ ํ•ต์‹ฌ ๊ฐœ๋…

์ค‘๋ณต๋˜๋Š” ๋ถ€๋ถ„ ๋ฌธ์ œ(Overlapping Subproblems)

  • ํฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ™์€ ์ž‘์€ ๋ฌธ์ œ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฐ˜๋ณตํ•ด์„œ ํ‘ธ๋Š” ๊ฒฝ์šฐ

  • ์˜ˆ์‹œ : ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜์—ด - f(n) = f(n-1) + f(n-2) ์ด๊ณ , f(n-1) ๊ณผ f(n-2) ๋ฅผ ๊ตฌํ•  ๋•Œ ๋˜ ๊ทธ ํ•˜์œ„ ๋ฌธ์ œ๋“ค์ด ๋ฐ˜๋ณต์ ์œผ๋กœ ํ˜ธ์ถœ๋จ.

์ตœ์  ๋ถ€๋ถ„ ๊ตฌ์กฐ (Optimal Substructure)

  • ๋ฌธ์ œ์˜ ์ตœ์  ํ•ด๊ฐ€ ๊ทธ ํ•˜์œ„ ๋ฌธ์ œ๋“ค์˜ ์ตœ์  ํ•ด๋ฅผ ์ด์šฉํ•ด ๊ตฌํ•  ์ˆ˜ ์žˆ์„ ๋•Œ

  • ์ฆ‰, ํ•˜์œ„ ๋ฌธ์ œ๋“ค์˜ ๋‹ต์„ ํ•ฉ์ณ์„œ ์ „์ฒด ๋ฌธ์ œ์˜ ๋‹ต์„ ๊ตฌํ•  ์ˆ˜ ์žˆ์Œ.


2. DP ์˜ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๋ฐฉ์‹ 1 : Top-Down(์žฌ๊ท€ + ๋ฉ”๋ชจ์ด์ œ์ด์…˜)

  • ํฐ ๋ฌธ์ œ๋ฅผ ํ’€๊ธฐ ์œ„ํ•ด ์žฌ๊ท€์ ์œผ๋กœ ์ž‘์€ ๋ฌธ์ œ๋“ค์„ ํ’€์–ด๊ฐ.

  • ์ด๋ฏธ ํ‘ผ ๋ฌธ์ œ๋Š” ๋ฉ”๋ชจ๋ฆฌ(๋ฐฐ์—ด, ๋”•์…”๋„ˆ๋ฆฌ ๋“ฑ) ์— ์ €์žฅํ•ด์„œ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜์ง€ ์•Š์Œ

  • Java ์˜ˆ์‹œ:

Map<Integer, Integer> memo = new HashMap<>();

int fib(int n) {
    if(n <= 1) return n;
    if(memo.containsKey(n)) return memo.get(n);
    int result = fib(n-1) + fib(n-2);
    memo.put(n, result);
    return result;
}

๋ฐฉ์‹ 2 : Bottom-Up (๋ฐ˜๋ณต๋ฌธ + ํ…Œ์ด๋ธ”)

  • ์ž‘์€ ๋ฌธ์ œ๋ถ€ํ„ฐ ์ฐจ๋ก€๋Œ€๋กœ ํ’€์–ด์„œ ๋‹ต์„ ๊ตฌํ•จ.

  • ๋ณ„๋„์˜ ์žฌ๊ท€ ํ˜ธ์ถœ์ด ์—†๊ณ , ๋ฐ˜๋ณต๋ฌธ์œผ๋กœ ๊ตฌํ˜„๋จ.

  • Java ์˜ˆ์‹œ:

int fib(int n) {
    if(n <= 1) return n;
    int[] db = 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];
}

3. ์ž์ฃผ ๋‚˜์˜ค๋Š” DP ๋ฌธ์ œ ์œ ํ˜•

๋ฌธ์ œ ์œ ํ˜•
์˜ˆ์‹œ
ํ‚ค ํฌ์ธํŠธ

1์ฐจ์› DP

ํ”ผ๋ณด๋‚˜์น˜, ๊ณ„๋‹จ ์˜ค๋ฅด๊ธฐ

dp[i] = dp[i-1] + dp[i-2]

2์ฐจ์› DP

LCS(Longest Common Subsequence), LCS

dp[i][j] ๋ฅผ ์˜๋ฏธ์ ์œผ๋กœ ์ •์˜

๋ฐฐ๋‚ญ ๋ฌธ์ œ

0/1 Knapsack

dp[i][w] = max(dp[i-1][w], dp[i-1][w-weight]+value)

๊ตฌ๊ฐ„ DP

ํŒฐ๋ฆฐ๋“œ๋กฌ ๋ถ„ํ• , ํ–‰๋ ฌ ๊ณฑ ์ตœ์ ํ™”

๊ตฌ๊ฐ„ dp[l][r] ์— ๋Œ€ํ•œ ์ ํ™”์‹

์ƒํƒœ ์••์ถ• DP

์—ฌํ–‰์ž ๋ฌธ์ œ, ์™ธํŒ์› ์ˆœํšŒ

๋น„ํŠธ ๋งˆ์Šคํฌ ํ™œ์šฉ

DP + DFS

๊ฒŒ์ž„ํŒ ํƒ์ƒ‰, ๊ฒฝ๋กœ ํƒ์ƒ‰

DFS ๋‚ด์—์„œ dp[x][y] ์ €์žฅ

DP + ์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ

์ตœ๋Œ€ ๋ถ€๋ถ„ํ•ฉ

๋ฉ”๋ชจ๋ฆฌ ์ตœ์ ํ™”


4. DP ๋ฌธ์ œ ํ’€์ด ์ˆœ์„œ

  1. ๋ฌธ์ œ๋ฅผ ๋ณด๊ณ  ์ค‘๋ณต๋˜๋Š” ๊ณ„์‚ฐ์ด ์žˆ๋Š”์ง€ ํŒŒ์•…

  2. ๋ฌธ์ œ๋ฅผ ์ž‘์€ ํ•˜์œ„ ๋ฌธ์ œ๋“ค๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋Š”์ง€ ํŒ๋‹จ.

  3. dp ๋ฐฐ์—ด(ํ˜น์€ ๋ฉ”๋ชจ ํ…Œ์ด๋ธ”)์˜ ์ •์˜์™€ ์˜๋ฏธ ๋ถ€์—ฌ

  4. ์ ํ™”์‹(์ด์ „ ์ƒํƒœ์—์„œ ํ˜„์žฌ ์ƒํƒœ๋กœ ๊ฐ€๋Š” ๋ฐฉ๋ฒ•) ๋„์ถœ

  5. ์ดˆ๊ธฐ๊ฐ’ ์„ค์ •

  6. ๋ฐ˜๋ณต๋ฌธ or ์žฌ๊ท€๋กœ ๊ตฌํ˜„

  7. ๋ฉ”๋ชจ๋ฆฌ๋‚˜ ์‹œ๊ฐ„ ์ตœ์ ํ™” ํ•„์š”์‹œ ์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ, ์ƒํƒœ ์••์ถ• ๋“ฑ ์ ์šฉ


5. ์˜ˆ์ œ : ๊ณ„๋‹จ ์˜ค๋ฅด๊ธฐ(ํ•œ ๋ฒˆ์— 1์นธ ๋˜๋Š” 2์นธ ์˜ค๋ฅผ ์ˆ˜ ์žˆ์Œ)

  • ๋ชฉํ‘œ : n ์นธ ๊ณ„๋‹จ์„ ์˜ค๋ฅด๋Š” ๋ฐฉ๋ฒ•์˜ ์ˆ˜

  • ์ ํ™”์‹ : dp[i] = dp[i - 1] + dp[i - 2]

  • ์ดˆ๊ธฐ๊ฐ’ : dp[0] = 1 , dp[1] = 1

int climbStairs(int n) {
    if(n <= 1) return 1;
    int[] dp = new int[n+1];
    dp[0] = 1;
    dp[1] = 1;
    for(int i = 2; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    return dp[n];
}

Last updated

Was this helpful?