λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
4️⃣ Python/Problem Solving

[Python Algorithm] 포도주 μ‹œμ‹ BOJ #2156

by seolhee2750 2022. 1. 31.
문제

https://www.acmicpc.net/problem/2156

 

2156번: 포도주 μ‹œμ‹

νš¨μ£ΌλŠ” 포도주 μ‹œμ‹νšŒμ— κ°”λ‹€. κ·Έ 곳에 κ°”λ”λ‹ˆ, ν…Œμ΄λΈ” μœ„μ— λ‹€μ–‘ν•œ 포도주가 λ“€μ–΄μžˆλŠ” 포도주 μž”μ΄ 일렬둜 놓여 μžˆμ—ˆλ‹€. νš¨μ£ΌλŠ” 포도주 μ‹œμ‹μ„ ν•˜λ €κ³  ν•˜λŠ”λ°, μ—¬κΈ°μ—λŠ” λ‹€μŒκ³Ό 같은 두 가지 규

www.acmicpc.net

 

λ‚΄ 문제 풀이
import sys

n = int(sys.stdin.readline())
wine = []
for _ in range(n):
    wine.append(int(sys.stdin.readline()))

if n == 1:
    print(wine[0])
elif n == 2:
    print(wine[0]+wine[1])
elif n == 3:
    print(max(wine[0]+wine[2], wine[1]+wine[2], max(wine[0]+wine[1], wine[0]+wine[2], wine[1]+wine[2])))
else:
    sums = [wine[0], wine[0]+wine[1]]
    sums.append(max(wine[0]+wine[2], wine[1]+wine[2], sums[1]))
    for i in range(3, n):
        sums.append(max(wine[i]+sums[i-2], wine[i]+wine[i-1]+sums[i-3], sums[i-1]))
    print(max(sums))

πŸ‘‰ DP 문제둜, 포도주λ₯Ό λ§ˆμ‹œλŠ” μ„Έ 가지 쑰건을 μ •ν•΄μ£ΌλŠ”κ²Œ 포인트 !

 

포도주λ₯Ό μ—°μ†ν•΄μ„œ 두 λ²ˆκΉŒμ§€ λ§ˆμ‹€ 수 μžˆμœΌλ―€λ‘œ,

ν•˜λ‚˜μ˜ μž” λ§ˆλ‹€ μ·¨ν•  수 μžˆλŠ” μžμ„Έλ₯Ό μ„Έ κ°€μ§€λ‘œ 정리할 수 μžˆλ‹€.
(wine은 μž…λ ₯받은 ν¬λ„μ£Όλ“€μ˜ 리슀트, sumsλŠ” μž” λ§ˆλ‹€ μ΅œλŒ€ λˆ„μ  포도주 μ–‘μ˜ λ¦¬μŠ€νŠΈμ΄λ‹€.)

  1. 이 μž”μ„ λ§ˆμ‹œλŠ” λŒ€μ‹ , 이전 μž”μ€ λ§ˆμ‹œμ§€ μ•ŠλŠ”λ‹€.
    => wine[i] + sums[i-2]
  2. 이 μž”μ„ λ§ˆμ‹œκ³ , 이전 μž”λ„ λ§ˆμ‹œλ©°, μ „μ „ μž”μ€ λ§ˆμ‹œμ§€ μ•ŠλŠ”λ‹€.
    => wine[i] + wine[i-1] + sums[i-3]
  3. 이 μž”μ„ λ§ˆμ‹œμ§€ μ•Šκ³ , 이전 μž”μ„ λ§ˆμ‹ λ‹€.
    => sums[i-1]

μœ„μ™€ 같이 ꡬ할 수 μžˆλŠ” 3κ°€μ§€μ˜ 경우의 수 쀑, κ°€μž₯ 큰 수λ₯Ό sums에 μ €μž₯ν•΄μ£Όλ©΄ λœλ‹€.

 

n이 1λΆ€ν„° 3κΉŒμ§€λŠ” μœ„μ˜ 싀행을 μ •μƒμ μœΌλ‘œ 진행할 수 μ—†κΈ° λ•Œλ¬Έμ— λ”°λ‘œ μ—°μ‚°ν–ˆκ³ ,

n이 4일 λ•Œ λΆ€ν„°λŠ” μœ„μ˜ μ„Έ 가지 쑰건에 μ˜ν•œ μ‹€ν–‰μœΌλ‘œ μž‘μ„±ν•΄μ£Όμ—ˆλ‹€. 

 

πŸ’‘ ν”Όλ“œλ°±
  • κ°„λ‹¨νžˆ μƒκ°ν•˜λ©΄ 정말 μ‰¬μš΄ 문제일 수 μžˆλŠ”λ°, λ‚˜λŠ” λ„ˆλ¬΄ λ³΅μž‘ν•˜κ²Œ μƒκ°ν•΄λ²„λ €μ„œ λ§Žμ€ μ‹œκ°„μ„ 썼닀..,
  • λ³΄ν†΅μ˜ DP λ¬Έμ œλ“€ 처럼, 주어진 μž…λ ₯을 μˆœμ„œλŒ€λ‘œ 각자의 쑰건을 μ •ν•΄μ£Όμ–΄ ν’€λ©΄ λ˜λŠ” λ¬Έμ œμ˜€λ‹€.
    DP문제λ₯Ό μ˜€λžœλ§Œμ— ν’€κΈ° μ‹œμž‘ν•˜λ‹ˆ λ‹€ κΉŒλ¨Ήμ—ˆλ‚˜λ³΄λ‹€,., 많이 곡뢀해야겠닀.

πŸ– [ μΆ”κ°€ ] λ‹€μ‹œ 풀어보기

import sys

n = int(sys.stdin.readline().strip())
if n == 1:
    print(int(sys.stdin.readline().strip()))
else:
    a = [0] # ν˜„μž¬ 포도주λ₯Ό λ§ˆμ‹œκ³ , 이전 ν¬λ„μ£ΌλŠ” λ§ˆμ‹œμ§€ μ•Šμ„ λ•Œ
    b = [0] # ν˜„μž¬ 포도주λ₯Ό λ§ˆμ‹œκ³ , 이전 포도주도 λ§ˆμ‹€ λ•Œ
    now = int(sys.stdin.readline().strip())
    a.append(now)
    b.append(now)
    for i in range(2, n+1):
        now = int(sys.stdin.readline().strip())
        a.append(max(max(a[:i-1]), max(b[:i-1])) + now)
        b.append(a[i-1] + now)
    print(max(max(a), max(b)))

πŸ‘‰ 첫 ν’€μ΄λ•ŒλŠ” μ„Έ 가지 경우의 수λ₯Ό λ§Œλ“€μ–΄μ£Όμ—ˆλŠ”λ°, μ΄λ²ˆμ—λŠ” '#2579 계단 였λ₯΄κΈ°'λ¬Έμ œμ™€ λΉ„μŠ·ν•˜κ²Œ ν’€μ—ˆλ‹€.

 

κ°€μž₯ λ¨Όμ € 생각해주어야 ν•  두 가지 경우의 수

  1. ν˜„μž¬ 포도주λ₯Ό λ§ˆμ‹€ λ•Œ, 이전 포도주λ₯Ό λ§ˆμ‹œμ§€ μ•Šμ•˜λ‹€κ³  κ°€μ •ν•  경우라면
    κ·Έ μ „ ν¬λ„μ£ΌλŠ” λ§ˆμ…¨μ„ μˆ˜λ„, μ•ˆλ§ˆμ…¨μ„ μˆ˜λ„ μžˆλ‹€. (이 뢀뢄이 계단 였λ₯΄κΈ° λ¬Έμ œμ™€μ˜ 차이점)
  2. ν˜„μž¬ 포도주λ₯Ό λ§ˆμ‹€ λ•Œ, 이전 포도주도 λ§ˆμ…¨λ‹€λ©΄
    κ·Έ μ „ ν¬λ„μ£ΌλŠ” λ§ˆμ…¨μœΌλ©΄ μ•ˆλœλ‹€.

μœ„μ™€ 같이 μƒκ°ν•˜μ—¬ a, b 리슀트λ₯Ό λ§Œλ“€μ–΄μ£Όμ—ˆκ³ 

b의 경우 μ „μ „ 포도주λ₯Ό λ§ˆμ…¨μœΌλ©΄ μ•ˆλ˜κΈ° λ•Œλ¬Έμ— λ°”λ‘œ a 리슀트의 μ „ λˆ„μ  값을 μΆ”κ°€ν•΄μ£Όμ—ˆλ‹€.

a의 κ²½μš°μ—λŠ” μ–Έμ œ λ§ˆμ§€λ§‰μœΌλ‘œ 포도주λ₯Ό λ§ˆμ…¨λŠ”μ§€ λͺ¨λ₯΄κΈ° λ•Œλ¬Έμ—, μ΄μ „μ˜ λˆ„μ  κ°’ 쀑 κ°€μž₯ 큰 값을 κ΅¬ν•΄μ„œ μΆ”κ°€ν–ˆλ‹€.

 

λŒ“κΈ€