๐Ÿค–/์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ •๋ฆฌ

๋™์  ๊ณ„ํš๋ฒ• (Dynamic Programming)

sssbin 2022. 3. 21. 21:38

 

์ค‘๋ณต๋˜๋Š” ์—ฐ์‚ฐ์„ ์ค„์ด์ž

- ์–ด๋–ค ๋ฌธ์ œ๋Š” ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์•ฝ๊ฐ„ ๋” ์‚ฌ์šฉํ•˜๋ฉด ์—ฐ์‚ฐ ์†๋„๋ฅผ ๋น„์•ฝ์ ์œผ๋กœ ์ฆ๊ฐ€์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค. 

- ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋Œ€ํ‘œ์ ์ธ ์˜ˆ์‹œ๋กœ๋Š” ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜์—ด์ด ์žˆ๋‹ค.

- ์ˆ˜ํ•™์  ์ ํ™”์‹์„ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์œผ๋กœ ํ‘œํ˜„ํ•˜๋ ค๋ฉด ์žฌ๊ท€ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ„๋‹จํ•˜๋‹ค.

# ํ”ผ๋ณด๋‚˜์น˜ ํ•จ์ˆ˜๋ฅผ ์žฌ๊ท€ ํ•จ์ˆ˜๋กœ ๊ตฌํ˜„

def fibo(x):
    if x == 1 or x == 2:
        return 1
    return fibo(x-1) + fibo(x-2)

print(fibo(4))

 

- ๊ทธ๋Ÿฐ๋ฐ ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜์—ด์˜ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•˜๋ฉด ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค.

- f(n) ํ•จ์ˆ˜์—์„œ n์ด ์ปค์ง€๋ฉด ์ปค์งˆ์ˆ˜๋ก ์ˆ˜ํ–‰ ์‹œ๊ฐ„์ด ๊ธฐํ•˜๊ธ‰์ˆ˜์ ์œผ๋กœ ๋Š˜์–ด๋‚˜๊ธฐ ๋•Œ๋ฌธ! -> O(2^N)

- ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜์—ด์˜ ํ˜ธ์ถœ ๊ณผ์ •์„ ๊ทธ๋ฆผ์„ ๊ทธ๋ ค ํ™•์ธํ•ด๋ณด๋ฉด ๋™์ผํ•œ ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜๋ณต์ ์œผ๋กœ ํ˜ธ์ถœ๋˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

- ์ด๋ฏธ ํ•œ ๋ฒˆ ๊ณ„์‚ฐํ–ˆ์ง€๋งŒ, ๊ณ„์† ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ๊ณ„์‚ฐํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

- ์ด์™€ ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์‚ฌ์šฉํ•˜๋ฉด ํšจ์œจ์ ์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

    ์กฐ๊ฑด1) ํฐ ๋ฌธ์ œ๋ฅผ ์ž‘์€ ๋ฌธ์ œ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.

    ์กฐ๊ฑด2) ์ž‘์€ ๋ฌธ์ œ์—์„œ ๊ตฌํ•œ ์ •๋‹ต์€ ๊ทธ๊ฒƒ์„ ํฌํ•จํ•˜๋Š” ํฐ ๋ฌธ์ œ์—์„œ๋„ ๋™์ผํ•˜๋‹ค.

- ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ๊ธฐ๋ฒ•(๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•œ ์ข…๋ฅ˜) = ์บ์‹ฑ

  : ํ•œ ๋ฒˆ ๊ตฌํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์— ๋ฉ”๋ชจํ•ด๋‘๊ณ  ๊ฐ™์€ ์‹์„ ๋‹ค์‹œ ํ˜ธ์ถœํ•˜๋ฉด ๋ฉ”๋ชจํ•œ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์˜ค๋Š” ๊ธฐ๋ฒ•

# ํ•œ ๋ฒˆ ๊ณ„์‚ฐ๋œ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ํ•˜๊ธฐ ์œ„ํ•œ ๋ฆฌ์ŠคํŠธ ์ดˆ๊ธฐํ™”
d = [0] * 100

# ํ”ผ๋ณด๋‚˜์น˜ ํ•จ์ˆ˜๋ฅผ ์žฌ๊ท€ํ•จ์ˆ˜๋กœ ๊ตฌํ˜„ (ํƒ‘๋‹ค์šด ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ)
def fibo(x):
    # ์ข…๋ฃŒ ์กฐ๊ฑด (1 ํ˜น์€ 2์ผ ๋•Œ 1์„ ๋ฐ˜ํ™˜)
    if x == 1 or x == 2:
        return 1
    # ์ด๋ฏธ ๊ณ„์‚ฐํ•œ ์  ์žˆ๋Š” ๋ฌธ์ œ๋ผ๋ฉด ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜
    if d[x] != 0:
        return d[x]
    # ์•„์ง ๊ณ„์‚ฐํ•˜์ง€ ์•Š์€ ๋ฌธ์ œ๋ผ๋ฉด ์ ํ™”์‹์— ๋”ฐ๋ผ์„œ ํ”ผ๋ณด๋‚˜์น˜ ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜
    d[x] = fibo(x-1) + fibo(x-2)
    return d[x]

print(fibo(99))

- ์ •๋ฆฌํ•˜์ž๋ฉด ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด๋ž€ ํฐ ๋ฌธ์ œ๋ฅผ ์ž‘๊ฒŒ ๋‚˜๋ˆ„๊ณ ,

   ๊ฐ™์€ ๋ฌธ์ œ๋ผ๋ฉด ํ•œ ๋ฒˆ์”ฉ๋งŒ ํ’€์–ด ๋ฌธ์ œ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ํ•ด๊ฒฐํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ธฐ๋ฒ•์ด๋‹ค.

- ๋ถ„ํ•  ์ •๋ณต ์•Œ๊ณ ๋ฆฌ์ฆ˜(ํ€ต์ •๋ ฌ)๊ณผ ๋‹ค๋ฅธ์ ์€ ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ๋ฌธ์ œ๋“ค์ด ์„œ๋กœ ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ.

- ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์ ์šฉํ–ˆ์„ ๋•Œ์˜ ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜์—ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” O(N)

    ใ„ด f(1) ๊ตฌํ•œ ๊ฐ’์ด f(2) ํ‘ธ๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๊ณ ,

        f(2)์˜ ๊ฐ’์ด f(3) ํ‘ธ๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๊ณ  ···

    ใ„ด ํ•œ ๋ฒˆ ๊ตฌํ•œ ๊ฒฐ๊ณผ๋Š” ๋‹ค์‹œ ๊ตฌํ•ด์ง€์ง€ ์•Š๋Š”๋‹ค.

f(6)์„ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ ์‹ค์ œ๋กœ ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜์— ๋Œ€ํ•ด์„œ ํ™•์ธ

# ํ”ผ๋ณด๋‚˜์น˜์—์„œ ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜ ํ™•์ธ

d = [0] * 100

def pibo(x):
    print('f(' + str(x) + ')', end=' ')
    if x == 1 or x == 2:
        return 1
    if d[x] != 0:
        return d[x]
    d[x] = pibo(x-1) + pibo(x-2)
    return d[x]

pibo(6)

 

- ์žฌ๊ท€ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„,

   ํฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์ž‘์€ ๋ฌธ์ œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค๊ณ  ํ•˜์—ฌ ํƒ‘๋‹ค์šด ๋ฐฉ์‹์ด๋ผ๊ณ  ๋งํ•œ๋‹ค. -> ํ•˜ํ–ฅ์‹

- ๋‹จ์ˆœํžˆ ๋ฐ˜๋ณต๋ฌธ์„ ์ด์šฉํ•˜์—ฌ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒฝ์šฐ

   ์ž‘์€ ๋ฌธ์ œ๋ถ€ํ„ฐ ์ฐจ๊ทผ์ฐจ๊ทผ ๋‹ต์„ ๋„์ถœํ•œ๋‹ค๊ณ  ํ•˜์—ฌ ๋ณดํ…€์—… ๋ฐฉ์‹์ด๋ผ๊ณ  ๋งํ•œ๋‹ค. -> ์ƒํ–ฅ์‹

# ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜์—ด (๋ฐ˜๋ณต์ )

# ์•ž์„œ ๊ณ„์‚ฐ๋œ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ DP ํ…Œ์ด๋ธ” ์ดˆ๊ธฐํ™”
d = [0] * 100

# ์ฒซ ๋ฒˆ์จฐ ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜์™€ ๋‘ ๋ฒˆ์งธ ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜๋Š” 1
d[1] = 1
d[2] = 1
n = 99

# ํ”ผ๋ณด๋‚˜์น˜ ํ•จ์ˆ˜ ๋ฐ˜๋ณต์ ์œผ๋กœ ๊ตฌํ˜„ (๋ณดํ…€์—… ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ)
for i in range(3, n+1):
    d[i] = d[i-1] + d[i-2]

print(d[n])

 

์‹ค์ „๋ฌธ์ œ1. 1๋กœ ๋งŒ๋“ค๊ธฐ

x = int(input())

# ์•ž์„œ ๊ณ„์‚ฐ๋œ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ DP ํ…Œ์ด๋ธ” ์ดˆ๊ธฐํ™”
d = [0] * 3001

# ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ง„ํ–‰ (๋ณดํ…€์—…)
for i in range(2, x+1):
    # ํ˜„์žฌ์˜ ์ˆ˜์—์„œ 1์„ ๋นผ๋Š” ๊ฒฝ์šฐ
    d[i] = d[i-1] + 1

    # ํ˜„์žฌ์˜ ์ˆ˜๊ฐ€ 2๋กœ ๋‚˜๋ˆ„์–ด ๋–จ์–ด์ง€๋Š” ๊ฒฝ์šฐ
    if i % 2 == 0:
        d[i] = min(d[i], d[i//2] + 1)

    # ํ˜„์žฌ์˜ ์ˆ˜๊ฐ€ 3์œผ๋กœ ๋‚˜๋ˆ„์–ด ๋–จ์–ด์ง€๋Š” ๊ฒฝ์šฐ
    if i % 3 == 0:
        d[i] = min(d[i], d[i//3] + 1)

    # ํ˜„์žฌ์˜ ์ˆ˜๊ฐ€ 5๋กœ ๋‚˜๋ˆ„์–ด ๋–จ์–ด์ง€๋Š” ๊ฒฝ์šฐ
    if i % 5 == 0:
        d[i] = min(d[i], d[i//5] + 1)

print(d[x])

 

์‹ค์ „๋ฌธ์ œ2. ๊ฐœ๋ฏธ ์ „์‚ฌ

n = int(input())
array = list(map(int, input().split()))

# ์•ž์„œ ๊ณ„์‚ฐ๋œ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ DP ํ…Œ์ด๋ธ”
d = [0] * 100

# ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ง„ํ–‰ (๋ณดํ…€์—…)
d[0] = array[0]
d[1] = max(array[0], array[1])
for i in range(2, n):
    d[i] = max(d[i-1], d[i-2] + array[i])

print(d[n-1])

 

์‹ค์ „๋ฌธ์ œ3. ๋ฐ”๋‹ฅ ๊ณต์‚ฌ 

n = int(input())

# ์•ž์„œ ๊ณ„์‚ฐ๋œ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ DP ํ…Œ์ด๋ธ” ์ดˆ๊ธฐํ™”
d = [0] * 1001

# ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ง„ํ–‰(๋ณดํ…€์—…)
d[1] = 1
d[2] = 3
for i in range(3, n+1):
    d[i] = (d[i-1] + 2 * d[i-2]) % 796796

print(d[n])

 

์‹ค์ „ ๋ฌธ์ œ4. ํšจ์œจ์ ์ธ ํ™”ํ ๊ตฌ์„ฑ

n, m = map(int, input().split())
values = []
for i in range(n):
    values.append(int(input()))

# ํ•œ ๋ฒˆ ๊ณ„์‚ฐ๋œ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ DP ํ…Œ์ด๋ธ” ์ดˆ๊ธฐํ™”
dp = [10001] * (m+1)

# ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ง„ํ–‰ (๋ณดํ…€์—…)
dp[0] = 0
for i in range(n):
    for j in range(values[i], m+1):
        if dp[j - values[i]] != 10001: # (i - k)์›์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์ด ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ
            dp[j] = min(dp[j], dp[j - values[i]] + 1)

if dp[m] == 10001: # ์ตœ์ข…์ ์œผ๋กœ M์›์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์ด ์—†๋Š” ๊ฒฝ์šฐ
    print(-1)
else:
    print(dp[m])