๊ด€๋ฆฌ ๋ฉ”๋‰ด

JiYoung Dev ๐Ÿ–ฅ

[ํŒŒ์ด์ฌ] ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํŒจ๋Ÿฌ๋‹ค์ž„ : Dynamic Programming ๋ณธ๋ฌธ

python

[ํŒŒ์ด์ฌ] ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํŒจ๋Ÿฌ๋‹ค์ž„ : Dynamic Programming

Shinjio 2023. 2. 27. 20:02

2023.02.27 ์ฝ”๋“œ์ž‡ ํ•™์Šต๋‚ด์šฉ

 

๐Ÿ”Ž Dynamic Programming

๋ณต์žกํ•œ ๋ฌธ์ œ๋ฅผ ๋” ์ž‘๊ณ  ๊ฐ„๋‹จํ•œ ํ•˜์œ„ ๋ฌธ์ œ๋กœ ๋ถ„ํ•ดํ•˜์—ฌ ๊ฐ๊ฐ์˜ ํ•˜์œ„ ๋ฌธ์ œ๋ฅผ ํ•œ ๋ฒˆ๋งŒ ํ’€๊ณ , ๊ฐ ํ•˜์œ„ ๋ฌธ์ œ์˜ ํ•ด๊ฒฐ์ฑ…์„ ํ‘œ์— ์ €์žฅํ•œ ํ›„ ํ•„์š”์— ๋”ฐ๋ผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํŒจ๋Ÿฌ๋‹ค์ž„.

 

Dynamic Programming์˜ ์กฐ๊ฑด

 

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

์ตœ์  ๋ถ€๋ถ„ ๊ตฌ์กฐ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์€ ๋ถ€๋ถ„ ๋ฌธ์ œ๋“ค์˜ ์ตœ์ ์˜ ๋‹ต์„ ์ด์šฉํ•˜์—ฌ ๊ธฐ์กด ๋ฌธ์ œ์˜ ์ตœ์ ์˜ ๋‹ต์„ ๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•จ.

์ฆ‰, ๊ธฐ์กด ๋ฌธ์ œ๋ฅผ ๋ถ€๋ถ„ ๋ฌธ์ œ๋กœ ๋‚˜๋ˆ„์–ด ํ’€ ์ˆ˜ ์žˆ์–ด์•ผ ํ•จ. (ex. ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜์—ด)

 

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

ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜์—ด๊ณผ ๊ฐ™์ด ์ตœ์  ๋ถ€๋ถ„ ๊ตฌ์กฐ๊ฐ€ ์žˆ๋Š” ๋ฌธ์ œ๋ฅผ ํ’€ ๋•Œ์—๋Š” ์ค‘๋ณต ๋˜๋Š” ๋ถ€๋ถ„ ๋ฌธ์ œ๋“ค์ด ์žˆ์„ ์ˆ˜ ์žˆ์Œ.

์˜ˆ๋ฅผ ๋“ค๋ฉด, ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜ ํ•จ์ˆ˜ fib(5)๋ฅผ ๊ตฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๊ณผ์ •์„ ๊ฑฐ์นจ

fib(5) = fib(4)                          + fib(3)
          = fib(3)              + fib(2) + fib(3)
          = fib(2) + fib(1) + fib(2) + fib(2) + fib(1)

 

์œ„์™€ ๊ฐ™์ด fib(5)๋ฅผ ํ‘ธ๋Š”๋ฐ fib(3) ์„ ์—ฌ๋Ÿฌ๋ฒˆ ๊ณ„์‚ฐํ•ด์•ผ ํ•จ. ์ด๋ ‡๊ฒŒ ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ํ‘ธ๋Š” ๊ฒƒ์€ ๋น„ํšจ์œจ์ .

์ด๋Ÿฌํ•œ ๋น„ํšจ์œจ์„ ํ•ด๊ฒฐํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํŒจ๋Ÿฌ๋‹ค์ž„์ด ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ

 

๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์œ„์™€ ๊ฐ™์ด ํ•œ ๋ฒˆ ๊ณ„์‚ฐํ•œ ๊ฒฐ๊ณผ๋ฅผ ํ‘œ์— ์ €์žฅํ•ด๋‘์—ˆ๋‹ค ํ•„์š”ํ•  ๋•Œ ๊บผ๋‚ด ์“ฐ๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉ

ํ•œ ๋ฒˆ ๊ณ„์‚ฐํ•œ ๊ฒฐ๊ณผ๋ฅผ ์žฌํ™œ์šฉํ•˜๋Š” ๋ฐฉ์‹

 

๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์—๋Š” Memoization๊ณผ Tabulation ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์Œ. 

 

๐Ÿ“– Memoization

์ค‘๋ณต๋˜๋Š” ๊ณ„์‚ฐ์€ ํ•œ ๋ฒˆ๋งŒ ๊ณ„์‚ฐ ํ›„ ๋ฉ”๋ชจํ•˜๊ณ  ๊ทธ ์ดํ›„์—๋Š” ๋ฉ”๋ชจ๋ฅผ ์ฐธ๊ณ ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ, ์žฌ๊ท€๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ.

๋ฉ”๋ชจ๋ฅผ ์ €์žฅํ•˜๋Š” ๊ณต๊ฐ„ ์ฆ‰, ๋‹ค์‹œ ์“ธ ๊ฐ’์„ ์ €์žฅํ•ด ๋‘๋Š” ๊ณต๊ฐ„์„ ์บ์‹œ(cache)๋ผ ํ•จ. ์ค‘๋ณต๋˜๋Š” ๊ณ„์‚ฐ์€ ์บ์‹œ์— ์ €์žฅํ•ด ๋‘๊ณ  ๋‹ค์‹œ ๊ณ„์‚ฐํ•ด์•ผ ํ•  ๋•Œ ๊บผ๋‚ด ์”€.

 

โ–ผโ–ผโ–ผ Memoization์œผ๋กœ ํ”ผ๋ณด๋‚˜์น˜ ํ•จ์ˆ˜ ์ž‘์„ฑ โ–ผโ–ผโ–ผ

โ‘  base case์™€ recursive ์ผ€์ด์Šค ์ฐพ๊ธฐ

    - base case : n์ด 1 ํ˜น์ธ 2์ผ ๋•Œ 1์„ ๋ฆฌํ„ดํ•จ

    - recursive case → 2๊ฐ€์ง€ ๊ฒฝ์šฐ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์Œ

      1) ์ด๋ฏธ cache์— ํ‚ค n์— ๋Œ€ํ•œ ๊ฐ’์ด ์ €์žฅ ๋˜์–ด ์žˆ์„ ๋•Œ → cache[n] ๋ฆฌํ„ด

      2) cache์— ํ‚ค n์— ๋Œ€ํ•œ ๊ฐ’์ด ์—†์„ ๋•Œ → ์žฌ๊ท€ ํ™œ์šฉํ•˜์—ฌ ํ‚ค n์— ๋Œ€ํ•œ ๊ฐ’์„ ๊ตฌํ•œ ํ›„ cache[n] ๋ฆฌํ„ด

 

 

์œ„์™€ ๊ฐ™์ด memoization์€ ๋งจ ์œ„์—์„œ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด ํ•˜๋‚˜์”ฉ ๋‚ด๋ ค๊ฐ€๋Š” ์‚ฌ๊ณ ๋ฐฉ์‹(ํ•˜ํ–ฅ์‹ ์ ‘๊ทผ, Top down approach).

memoization๊ณผ ๋ฐ˜๋Œ€๋กœ f(1)๋ถ€ํ„ฐ ์ฐจ๋ก€๋Œ€๋กœ ๊ณ„์‚ฐํ•˜์—ฌ ๊ตฌ๋™ํ•˜๋Š” Bottom-up approach ๋ฐฉ์‹์ด ์žˆ์Œ. ์ด ๋ฐฉ์‹ ๋˜ํ•œ ํ•œ ๋ฒˆ๋งŒ ๊ณ„์‚ฐํ•˜๋ฏ€๋กœ dynamic programming ์ค‘ ํ•˜๋‚˜. ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์„ Tabulation์ด๋ผ ํ•จ. 

 

๐Ÿ“– Tabulation

Table ๋ฐฉ์‹์œผ๋กœ ์ •๋ฆฌํ•œ๋‹ค๋Š” ๋œป์œผ๋กœ ๋ฐ˜๋ณต๋ฌธ์„ ์‚ฌ์šฉํ•ด์„œ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ฑ„์›Œ๋‚˜๊ฐ€๊ฒŒ ๋จ

 

โ–ผโ–ผโ–ผ Tabulation์œผ๋กœ ํ”ผ๋ณด๋‚˜์น˜ ํ•จ์ˆ˜ ์ž‘์„ฑ โ–ผโ–ผโ–ผ

โ‘  ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜๋ฅผ ์ €์žฅํ•  ๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ (tab) ํ•˜๊ณ  0 ~ 2๋ฒˆ์งธ ๊ฐ’ ๋„ฃ๊ธฐ

     → ๋ฆฌ์ŠคํŠธ๋Š” ์ธ๋ฑ์Šค 0๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋ฏ€๋กœ n๋ฒˆ์งธ์˜ ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด์„œ ์ธ๋ฑ์Šค 0์— 0 ์ž…๋ ฅ

โ‘ก ๋ฐ˜๋ณต๋ฌธ ์‚ฌ์šฉํ•˜์—ฌ tab์— ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜ ์ถ”๊ฐ€

 

 

โ–ผโ–ผโ–ผ Tabulation์œผ๋กœ ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜ ์ฐพ๊ธฐ (๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ) โ–ผโ–ผโ–ผ

์ฐจ์ด์  : ๋ฆฌ์ŠคํŠธ ๋Œ€์‹  ๋”•์…”๋„ˆ๋ฆฌ, for๋ฌธ ๋Œ€์‹  while๋ฌธ ํ™œ์šฉํ•˜์—ฌ ์ž‘์„ฑ

 

๐Ÿ“– Memoization vs Tabulation

๊ณตํ†ต์  : ์ค‘๋ณต๋˜๋Š” ๋ถ€๋ถ„ ๋ฌธ์ œ์˜ ๋น„ํšจ์œจ์„ ํ•ด๊ฒฐ

์ฐจ์ด์  : Memoization์€ ์žฌ๊ท€ํ•จ์ˆ˜, Tabulation์€ ๋ฐ˜๋ณต๋ฌธ์„ ์‚ฌ์šฉ

memoization์˜ ๊ฒฝ์šฐ ์žฌ๊ท€ ํ•จ์ˆ˜๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์žฌ๊ท€ ํ˜ธ์ถœ์ด ๋„ˆ๋ฌด ๋งŽ์ด ์ผ์–ด๋‚˜๋ฉด ์Šคํƒ์ด ์Œ“์—ฌ ๊ณผ๋ถ€ํ•˜๊ฐ€ ๋˜์–ด ์˜ค๋ฅ˜ ๋ฐœ์ƒ. ๋ฐ˜๋ฉด, Tabulation์€ ์ฒ˜์Œ๋ถ€ํ„ฐ n๋ฒˆ์งธ๊นŒ์ง€ ๋ชจ๋‘ ๊ณ„์‚ฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ค‘๊ฐ„์— ํ•„์š”์—†๋Š” ๋ถ€๋ถ„๊นŒ์ง€ ๊ณ„์‚ฐํ•˜๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์„ ์ˆ˜ ์žˆ์Œ. memoization์€ ๋’ค์—์„œ๋ถ€ํ„ฐ ํ•„์š”ํ•œ ๊ณ„์‚ฐ์„ ์š”๊ตฌํ•˜๋Š” ํ˜•ํƒœ์ด๋ฏ€๋กœ ๋ถˆํ•„์š”ํ•œ ๊ณ„์‚ฐ์€ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Œ.

 

Tabulation์œผ๋กœ ํ”ผ๋ณด๋‚˜์น˜ ํ•จ์ˆ˜ ํ’€ ๊ฒฝ์šฐ

์‹œ๊ฐ„ ๋ณต์žก๋„ : O(n)

๊ณต๊ฐ„ ๋ณต์žก๋„ : O(n)

tabulation์€ ๋ฆฌ์ŠคํŠธ์— ๋ชจ๋“  ๊ณ„์‚ฐ ๊ฐ’์„ ์ €์žฅํ•จ → ๊ณต๊ฐ„ ๋ณต์žก๋„๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•ด ๊ฐ€์žฅ ์ตœ๊ทผ ๊ฐ’ 2๊ฐœ๋งŒ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ €์žฅํ•˜๋ฉด ๊ณต๊ฐ„ ๋ณต์žก๋„๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์Œ(current, previous) → ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ๋Š” ๊ณ ์ •๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ณต๊ฐ„๋ณต์žก๋„๋Š” O(1)์ด ๋จ

 

โ–ผโ–ผโ–ผ ๊ณต๊ฐ„ ๋ณต์žก๋„ O(1)์ธ ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜ ํ•จ์ˆ˜ ์ž‘์„ฑ โ–ผโ–ผโ–ผ

์ž„์‹œ ์ €์žฅ ๋ณ€์ˆ˜ ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ ์ฝ”๋“œ :
for i in range(1, n)
    temp = current
    current = current + previous
    previous = temp

์ž„์‹œ ์ €์žฅ ๋ณ€์ˆ˜ ์ƒ๋žตํ•œ ๊ฒฝ์šฐ ์ฝ”๋“œ :
for i in range(1, n)
    current, previos = current + previous, current

 

โ–ผโ–ผโ–ผ ๊ณต๊ฐ„ ๋ณต์žก๋„ O(1)์ธ ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜ ํ•จ์ˆ˜ ์ž‘์„ฑ(๋‚ด๊ฐ€ ์ž‘์„ฑ) โ–ผโ–ผโ–ผ

์ž„์‹œ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์„ฑํ•˜์˜€๊ณ , temp์— previous ๊ฐ’์„ ์ €์žฅ

 

์ž„์‹œ ์ €์žฅ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ํ•œ์ค„๋กœ ์ž‘์„ฑํ•œ ์ฝ”๋“œ