๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“š Computer Science/Algorithm

[์•Œ๊ณ ๋ฆฌ์ฆ˜] ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ(Dynamic Programming)

by hyebin (Helia) 2022. 3. 30.
๋ฐ˜์‘ํ˜•

์ปดํ“จํ„ฐ๋ฅผ ํ™œ์šฉํ•ด๋„ ์–ด๋ ค์šด ๋ฌธ์ œ

  • ์ตœ์ ์˜ ํ•ด๋ฅผ ๊ตฌํ•˜๊ธฐ์— ์‹œ๊ฐ„์ด ๋งค์šฐ ๋งŽ์ด ํ•„์š”ํ•œ ๋ฌธ์ œ
  • ์ตœ์ ์˜ ํ•ด๋ฅผ ๊ตฌํ•˜๊ธฐ์— ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์ด ๋งค์šฐ ๋งŽ์ด ํ•„์š”ํ•œ ๋ฌธ์ œ

์ปดํ“จํ„ฐ๋Š” ์—ฐ์‚ฐ ์†๋„์— ํ•œ๊ณ„๊ฐ€ ์žˆ๊ณ , ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ์˜ ๊ฐœ์ˆ˜๋„ ํ•œ์ •์ ์ด๋ผ ๋งŽ์€ ์ œ์•ฝ ๋ฐœ์ƒ

โ˜ž ์—ฐ์‚ฐ ์†๋„์™€ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์ตœ๋Œ€ํ•œ์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํšจ์œจ์ ์ธ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ž‘์„ฑ ํ•„์š”

 

๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ(Dynamic Programming)

  • ๋™์  ๊ณ„ํš๋ฒ•
  • ํฐ ๋ฌธ์ œ๋ฅผ ์ž‘๊ฒŒ ๋‚˜๋ˆ„๊ณ , ๊ฐ™์€ ๋ฌธ์ œ๋ผ๋ฉด ํ•œ ๋ฒˆ์”ฉ๋งŒ ํ’€์–ด ๋ฌธ์ œ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ํ•ด๊ฒฐํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ธฐ๋ฒ•
  • ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์•ฝ๊ฐ„ ๋” ์‚ฌ์šฉํ•˜๋ฉด ์—ฐ์‚ฐ ์†๋„๋ฅผ ๋น„์•ฝ์ ์œผ๋กœ ์ฆ๊ฐ€์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•
  • ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ๋‹ค์Œ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•  ๋•Œ๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
    • ํฐ ๋ฌธ์ œ๋ฅผ ์ž‘์€ ๋ฌธ์ œ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.
    • ์ž‘์€ ๋ฌธ์ œ์—์„œ ๊ตฌํ•œ ์ •๋‹ต์€ ๊ทธ๊ฒƒ์„ ํฌํ•จํ•˜๋Š” ํฐ ๋ฌธ์ œ์—์„œ๋„ ๋™์ผํ•˜๋‹ค
๋ถ„ํ•  ์ •๋ณต(Divide and Conquer) ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ์ฐจ์ด์ 
=> ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ๋ฌธ์ œ๋“ค์ด ์„œ๋กœ ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ณ  ์žˆ์Œ

 

๋ฉ”๋ชจ์ด์ œ์ด์…˜(Memoization) ๊ธฐ๋ฒ•

  • ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•œ ์ข…๋ฅ˜
  • ๊ฐ’์„ ์ €์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋ฏ€๋กœ ์บ์‹ฑ(Caching)์ด๋ผ๊ณ ๋„ ํ•จ
  • ํ•œ๋ฒˆ ๊ตฌํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์— ๋ฉ”๋ชจํ•ด๋‘๊ณ  ๊ฐ™์€ ์‹์„ ๋‹ค์‹œ ํ˜ธ์ถœํ•˜๋ฉด ๋ฉ”๋ชจํ•œ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์˜ค๋Š” ๊ธฐ๋ฒ•

ํƒ‘๋‹ค์šด(Top-Down) ๋ฐฉ์‹

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

๋ณดํ…€์—…(Botton-Up) ๋ฐฉ์‹

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

๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฌธ์ œ

1๋กœ ๋งŒ๋“ค๊ธฐ

์ •์ˆ˜ X๊ฐ€ ์ฃผ์–ด์งˆ ๋•Œ ์ •์ˆ˜ X์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์—ฐ์‚ฐ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด 4๊ฐ€์ง€์ด๋‹ค.
    1. X๊ฐ€ 5๋กœ ๋‚˜๋ˆ„์–ด ๋–จ์–ด์ง€๋ฉด, 5๋กœ ๋‚˜๋ˆˆ๋‹ค.
    2. X๊ฐ€ 3์œผ๋กœ ๋‚˜๋ˆ„์–ด ๋–จ์–ด์ง€๋ฉด, 3์œผ๋กœ ๋‚˜๋ˆˆ๋‹ค.
    3. X๊ฐ€ 2๋กœ ๋‚˜๋ˆ„์–ด ๋–จ์–ด์ง€๋ฉด, 2๋กœ ๋‚˜๋ˆˆ๋‹ค.
    4. X์—์„œ 1์„ ๋บ€๋‹ค.

์ •์ˆ˜ X๊ฐ€ ์ฃผ์–ด์กŒ์„ ๋•Œ, ์—ฐ์‚ฐ 3๊ฐœ๋ฅผ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•ด์„œ 1์„ ๋งŒ๋“ค๋ ค๊ณ  ํ•œ๋‹ค. ์—ฐ์‚ฐ์„ ์‚ฌ์šฉํ•˜๋Š” ํšŸ์ˆ˜์˜ ์ตœ์†Ÿ๊ฐ’์„ ์ถœ๋ ฅํ•˜์‹œ์˜ค.
let x = Int(readLine()!)!

var d: [Int] = Array(repeating: 0, count: 30001)

//๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ง„ํ–‰(๋ณดํ…€์—…)
for i in 2..<(x+1){
    d[i] = d[i-1] + 1
    if i%2 == 0{
        d[i] = min(d[i], d[i/2]+1)
    }
    if i%3 == 0{
        d[i] = min(d[i], d[i/3]+1)
    }
    if i%5 == 0{
        d[i] = min(d[i], d[i/5]+1)
    }
}
print(d[x])

๊ฐœ๋ฏธ ์ „์‚ฌ

๊ฐœ๋ฏธ ์ „์‚ฌ๋Š” ๋ถ€์กฑํ•œ ์‹๋Ÿ‰์„ ์ถฉ๋‹นํ•˜๊ณ ์ž ๋ฉ”๋šœ๊ธฐ ๋งˆ์„์˜ ์‹๋Ÿ‰์ฐฝ๊ณ ๋ฅผ ๋ชฐ๋ž˜ ๊ณต๊ฒฉํ•˜๋ ค๊ณ  ํ•œ๋‹ค.
๋ฉ”๋šœ๊ธฐ ๋งˆ์„์—๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์‹๋Ÿ‰์ฐฝ๊ณ ๊ฐ€ ์žˆ๋Š”๋ฐ ์‹๋Ÿ‰์ฐฝ๊ณ ๋Š” ์ผ์ง์„ ์œผ๋กœ ์ด์–ด์ ธ ์žˆ๋‹ค.
๊ฐ ์‹๋Ÿ‰์ฐฝ๊ณ ์—๋Š” ์ •ํ•ด์ง„ ์ˆ˜์˜ ์‹๋Ÿ‰์„ ์ €์žฅํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ๊ฐœ๋ฏธ ์ „์‚ฌ๋Š” ์‹๋Ÿ‰์ฐฝ๊ณ ๋ฅผ ์„ ํƒ์ ์œผ๋กœ ์•ฝํƒˆํ•˜์—ฌ ์‹๋Ÿ‰์„ ๋นผ์•—์„ ์˜ˆ์ •์ด๋‹ค.
์ด๋•Œ ๋ฉ”๋šœ๊ธฐ ์ •์ฐฐ๋ณ‘๋“ค์€ ์ผ์ง์„ ์ƒ์— ์กด์žฌํ•˜๋Š” ์‹๋Ÿ‰์ฐฝ๊ณ  ์ค‘์—์„œ ์„œ๋กœ ์ธ์ ‘ํ•œ ์‹๋Ÿ‰์ฐฝ๊ณ ๊ฐ€ ๊ณต๊ฒฉ๋ฐ›์œผ๋ฉด ๋ฐ”๋กœ ์•Œ์•„์ฑŒ ์ˆ˜ ์žˆ๋‹ค.
๋”ฐ๋ผ์„œ ๊ฐœ๋ฏธ ์ „์‚ฌ๊ฐ€ ์ •์ฐฐ๋ณ‘์—๊ฒŒ ๋“คํ‚ค์ง€ ์•Š๊ณ  ์‹๋Ÿ‰์ฐฝ๊ณ ๋ฅผ ์•ฝํƒˆํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ตœ์†Œํ•œ ํ•œ ์นธ ์ด์ƒ ๋–จ์–ด์ง„ ์‹๋Ÿ‰์ฐฝ๊ณ ๋ฅผ ์•ฝํƒˆํ•ด์•ผ ํ•œ๋‹ค.

๊ฐœ๋ฏธ ์ „์‚ฌ๋ฅผ ์œ„ํ•ด ์‹๋Ÿ‰์ฐฝ๊ณ  N๊ฐœ์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ์ฃผ์–ด์กŒ์„ ๋•Œ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์‹๋Ÿ‰์˜ ์ตœ๋Œ“๊ฐ’์„ ๊ตฌํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜์‹œ์˜ค.

i ๋ฒˆ์งธ ์‹๋Ÿ‰์ฐฝ๊ณ ์— ์žˆ๋Š” ์‹๋Ÿ‰์ด k๋ผ๊ณ  ํ–ˆ์„ ๋•Œ, ์ ํ™”์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

$$a_{i} = max(a_{i-1}, a_{i-2}+k_{i})$$
var n = Int(readLine()!)!
var arr = readLine()!.split(separator: " ").map{Int(String($0))!}

var d: [Int] = Array(repeating: 0, count: 100)
d[0] = arr[0]
d[1] = max(arr[0],arr[1])

for i in 2..<n{
    d[i] = max(d[i-1],d[i-2]+arr[i])
}

print(d[n-1])

๋ฐ”๋‹ฅ ๊ณต์‚ฌ

๊ฐ€๋กœ์˜ ๊ธธ์ด๊ฐ€ N, ์„ธ๋กœ์˜ ๊ธธ์ด๊ฐ€ 2์ธ ์ง์‚ฌ๊ฐํ˜• ํ˜•ํƒœ์˜ ์–‡์€ ๋ฐ”๋‹ฅ์ด ์žˆ๋‹ค.
ํƒœ์ผ์ด์€ ์ด ์–‡์€ ๋ฐ”๋‹ฅ์„ 1x2์˜ ๋ฎ๊ฐœ,  2x1์˜ ๋ฎ๊ฐœ, 2x2์˜ ๋ฎ๊ฐœ๋ฅผ ์ด์šฉํ•ด ์ฑ„์šฐ๊ณ ์ž ํ•œ๋‹ค.

์ด๋•Œ ๋ฐ”๋‹ฅ์„ ์ฑ„์šฐ๋Š” ๋ชจ๋“  ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ๊ตฌํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜์‹œ์˜ค. 
- 2xN ๋ฐ”๋‹ฅ์„ ์ฑ„์šฐ๋Š” ๋ฐฉ๋ฒ•์˜ ์ˆ˜๋ฅผ 796,796์œผ๋กœ ๋‚˜๋ˆˆ ๋‚˜๋จธ์ง€๋ฅผ ์ถœ๋ ฅํ•˜์‹œ์˜ค.

์œ„ ๋ฌธ์ œ์˜ ์ ํ™”์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

$$ a_{i} = a_{i-1} + a_{i-2} * 2 $$
var n = Int(readLine()!)!

var d: [Int] = Array(repeating: 0, count: 1001)
d[0] = 1
d[1] = 3

for i in 2..<n{
    d[i] = (d[i-1]+d[i-2]*2) % 796796
}

print(d[n-1])

ํšจ์œจ์ ์ธ ํ™”ํ ๊ตฌ์„ฑ

N๊ฐ€์ง€ ์ข…๋ฅ˜์˜ ํ™”ํ๊ฐ€ ์žˆ๋‹ค. ์ด ํ™”ํ๋“ค์˜ ๊ฐœ์ˆ˜๋ฅผ ์ตœ์†Œํ•œ์œผ๋กœ ์ด์šฉํ•ด์„œ ๊ทธ ๊ฐ€์น˜์˜ ํ•ฉ์ด M์›์ด ๋˜๋„๋ก ํ•˜๋ ค๊ณ  ํ•œ๋‹ค.
์ด๋•Œ ๊ฐ ํ™”ํ๋Š” ๋ช‡ ๊ฐœ๋ผ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์‚ฌ์šฉํ•œ ํ™”ํ์˜ ๊ตฌ์„ฑ์€ ๊ฐ™์ง€๋งŒ ์ˆœ์„œ๋งŒ ๋‹ค๋ฅธ ๊ฒƒ์€ ๊ฐ™์€ ๊ฒฝ์šฐ๋กœ ๊ตฌ๋ถ„ํ•œ๋‹ค.
M์›์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•  ๊ฒฝ์šฐ -1์„ ์ถœ๋ ฅํ•œ๋‹ค.

๊ธˆ์•ก i๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์ตœ์†Œํ•œ์˜ ํ™”ํ ๊ฐœ์ˆ˜๋ฅผ a_i, ํ™”ํ์˜ ๋‹จ์œ„๋ฅผ k๋ผ๊ณ  ํ–ˆ์„ ๋•Œ ์ ํ™”์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

a_(i-k) ๋Š” ๊ธˆ์•ก (i-k)๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์ตœ์†Œํ•œ์˜ ํ™”ํ ๊ฐœ์ˆ˜์ด๋‹ค.

$$ a_{i} = min(a_{i}, a_{i-k} + 1) $$
var inputdata = readLine()!.split(separator: " ").map{Int(String($0))!}
var n = inputdata[0], m = inputdata[1]

var arr = [Int]()
for _ in 0..<n{ arr.append(Int(readLine()!)!)}

var d: [Int] = Array(repeating: 10001, count: m+1)
d[0] = 0

for i in 1..<n{
    for j in min(arr[i],m)...max(arr[i],m){
        var index = j - arr[i] > 0 ? j - arr[i] : m + j - arr[i]
        if d[index] != 10001{
            d[j] = min(d[j], d[index]+1)
        }
    }
}

d[m] == 10001 ? print(-1) : print(d[m])
๋ฐ˜์‘ํ˜•