파이썬 μ•Œκ³ λ¦¬μ¦˜

[μ΄μ½”ν…Œ Ch8-5] 효율적인 화폐 ꡬ성 (DP)

은진 2022. 2. 6. 21:17

πŸ‘©πŸ»β€πŸ’»λ¬Έμ œμ„€λͺ…

[μ΄μ½”ν…Œ Ch8-5] 효율적인 화폐 ꡬ성 (DP)
μ΄μ½”ν…Œ

N가지 μ’…λ₯˜μ˜ 화폐가 μžˆλ‹€. 이 ν™”νλ“€μ˜ 개수λ₯Ό μ΅œμ†Œν•œμœΌλ‘œ μ΄μš©ν•΄μ„œ κ·Έ κ°€μΉ˜μ˜ 합이 M원이 λ˜λ„λ‘ ν•˜λ €κ³  ν•œλ‹€. μ΄λ•Œ 각 νšŒνλŠ” λͺ‡ κ°œλΌλ„ μ‚¬μš©ν•  수 있으며, μ‚¬μš©ν•œ ν™”νμ˜ ꡬ성은 κ°™μ§€λ§Œ μˆœμ„œλ§Œ λ‹€λ₯Έ 것은 같은 경우둜 κ΅¬λΆ„ν•œλ‹€. 예λ₯Ό λ“€μ–΄ 2원, 3원 λ‹¨μœ„μ˜ 화폐가 μžˆμ„ λ•ŒλŠ” 15원을 λ§Œλ“€κΈ° μœ„ν•΄ 3원을
5개 μ‚¬μš©ν•˜λŠ” 것이 κ°€μž₯ μ΅œμ†Œν•œμ˜ 화폐 κ°œμˆ˜μ΄λ‹€.


μž…λ ₯ 쑰건

  • 첫째 쀄에 N, M이 주어진닀. (1 <= N <= 100, 1 <= M <= 10,000)
  • 이후 N개의 μ€„μ—λŠ” 각 ν™”νμ˜ κ°€μΉ˜κ°€ 주어진닀. 화폐 κ°€μΉ˜λŠ” 10,000보닀 μž‘κ±°λ‚˜ 같은 μžμ—°μˆ˜μ΄λ‹€.

좜λ ₯ 쑰건

  • 첫째 쀄에 M원을 λ§Œλ“€κΈ° μœ„ν•œ μ΅œμ†Œν•œμ˜ 화폐 개수λ₯Ό 좜λ ₯ν•œλ‹€.
  • λΆˆκ°€λŠ₯ν•  λ•ŒλŠ” -1을 좜λ ₯ν•œλ‹€.


μž…λ ₯ μ˜ˆμ‹œ 1

2 15
2
3

좜λ ₯ μ˜ˆμ‹œ 1

5


μž…λ ₯ μ˜ˆμ‹œ 2

3 4
3
5
7

좜λ ₯ μ˜ˆμ‹œ 2

-1


✍️Idea Sketch

μ•Œκ³ λ¦¬μ¦˜ : λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°, Bottom-Up


μ‹œκ°„λ³΅μž‘λ„

O(NM) : μ΄μ€‘λ°˜λ³΅λ¬Έ

이 λ¬Έμ œλŠ” μž‘μ€ λ¬Έμ œλΆ€ν„° μ°¨κ·Όμ°¨κ·Ό 닡을 λ„μΆœν•˜λŠ” Bottom-Up λ°©μ‹μœΌλ‘œ κ΅¬ν˜„ν–ˆλ‹€. κ°€μΉ˜ 1원뢀터(μž‘μ€ κ°€μΉ˜λΆ€ν„°) κ°€μΉ˜ Mμ›κΉŒμ§€ νƒμƒ‰ν•˜λ©°, ν•œ 번 탐색할 λ•Œλ§ˆλ‹€ λͺ¨λ“  화폐λ₯Ό ν™•μΈν•œλ‹€. 화폐 μ’…λ₯˜λŠ” Nκ°œμ΄λ―€λ‘œ μ‹œκ°„λ³΅μž‘λ„λŠ” O(M*N)이 λœλ‹€.


βœοΈλ‚΄ μ†ŒμŠ€μ½”λ“œ

  • dp λ°°μ—΄μ˜ indexλŠ” κ°€μΉ˜, valueλŠ” 화폐 κ°œμˆ˜μ΄λ‹€. μ²˜μŒμ—λŠ” valueλ₯Ό λ¬΄ν•œλŒ€ κ°’μœΌλ‘œ μ΄ˆκΈ°ν™”ν•œλ‹€. 단 κ°€μΉ˜ 0원을 λ§Œλ“€κΈ° μœ„ν•΄ ν•„μš”ν•œ 화폐 κ°œμˆ˜λŠ” 0κ°œμ΄λ―€λ‘œ dp[0] = 0이닀.
  • κ°€μΉ˜ 1원뢀터 κ°€μΉ˜ Mμ›κΉŒμ§€ νƒμƒ‰ν•˜λ©°, ν•œ 번 탐색할 λ•Œλ§ˆλ‹€ λͺ¨λ“  화폐λ₯Ό νƒμƒ‰ν•œλ‹€. (μ΄μ€‘λ°˜λ³΅λ¬Έ)
  • κ°€μΉ˜ m원을 λ§Œλ“€κΈ° μœ„ν•΄ ν•„μš”ν•œ 화폐 κ°œμˆ˜κ°€ λ¬΄ν•œλŒ€μΈ 경우 λΆˆκ°€λŠ₯ν•˜λ‹€λŠ” λœ»μ΄λ―€λ‘œ -1을 좜λ ₯ν•œλ‹€.
  import sys
  si = sys.stdin.readline

  n, m = map(int, si().split())
  coins = [int(si()) for _ in range(n)]

  dp = [float('inf')] * (m + 1)
  dp[0] = 0

  for i in range(1, m + 1):
    for coin in coins:
      if i >= coin:
        dp[i] = min(dp[i], dp[i - coin] + 1)

  if dp[m] == float('inf'):
    print(-1)
  else:
    print(dp[m])