μ•Œκ³ λ¦¬μ¦˜/DP

[λ°±μ€€ 2156 πŸ₯ˆ] 포도주 μ‹œμ‹

1eehyunji 2023. 11. 4. 01:22

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

 

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

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

www.acmicpc.net

문제

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

  1. 포도주 μž”μ„ μ„ νƒν•˜λ©΄ κ·Έ μž”μ— λ“€μ–΄μžˆλŠ” ν¬λ„μ£ΌλŠ” λͺ¨λ‘ λ§ˆμ…”μ•Ό ν•˜κ³ , λ§ˆμ‹  ν›„μ—λŠ” μ›λž˜ μœ„μΉ˜μ— λ‹€μ‹œ 놓아야 ν•œλ‹€.
  2. μ—°μ†μœΌλ‘œ 놓여 μžˆλŠ” 3μž”μ„ λͺ¨λ‘ λ§ˆμ‹€ μˆ˜λŠ” μ—†λ‹€.

νš¨μ£ΌλŠ” 될 수 μžˆλŠ” λŒ€λ‘œ λ§Žμ€ μ–‘μ˜ 포도주λ₯Ό 맛보기 μœ„ν•΄μ„œ μ–΄λ–€ 포도주 μž”μ„ 선택해야 ν• μ§€ κ³ λ―Όν•˜κ³  μžˆλ‹€. 1λΆ€ν„° nκΉŒμ§€μ˜ λ²ˆν˜Έκ°€ λΆ™μ–΄ μžˆλŠ” n개의 포도주 μž”μ΄ μˆœμ„œλŒ€λ‘œ ν…Œμ΄λΈ” μœ„μ— 놓여 있고, 각 포도주 μž”μ— λ“€μ–΄μžˆλŠ” ν¬λ„μ£Όμ˜ 양이 μ£Όμ–΄μ‘Œμ„ λ•Œ, 효주λ₯Ό 도와 κ°€μž₯ λ§Žμ€ μ–‘μ˜ 포도주λ₯Ό λ§ˆμ‹€ 수 μžˆλ„λ‘ ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€. 

예λ₯Ό λ“€μ–΄ 6개의 포도주 μž”μ΄ 있고, 각각의 μž”μ— μˆœμ„œλŒ€λ‘œ 6, 10, 13, 9, 8, 1 만큼의 포도주가 λ“€μ–΄ μžˆμ„ λ•Œ, 첫 번째, 두 번째, λ„€ 번째, λ‹€μ„― 번째 포도주 μž”μ„ μ„ νƒν•˜λ©΄ 총 포도주 양이 33으둜 μ΅œλŒ€λ‘œ λ§ˆμ‹€ 수 μžˆλ‹€.

μž…λ ₯

첫째 쀄에 포도주 μž”μ˜ 개수 n이 μ£Όμ–΄μ§„λ‹€. (1 ≤ n ≤ 10,000) λ‘˜μ§Έ 쀄뢀터 n+1번째 μ€„κΉŒμ§€ 포도주 μž”μ— λ“€μ–΄μžˆλŠ” ν¬λ„μ£Όμ˜ 양이 μˆœμ„œλŒ€λ‘œ μ£Όμ–΄μ§„λ‹€. ν¬λ„μ£Όμ˜ 양은 1,000 μ΄ν•˜μ˜ 음이 μ•„λ‹Œ μ •μˆ˜μ΄λ‹€.

좜λ ₯

첫째 쀄에 μ΅œλŒ€λ‘œ λ§ˆμ‹€ 수 μžˆλŠ” ν¬λ„μ£Όμ˜ 양을 좜λ ₯ν•œλ‹€.

문제 풀이

  • 이전에 ν’€μ—ˆλ˜ λ°±μ€€ 2579번 계단 λ¬Έμ œμ™€ μœ μ‚¬ν•΄μ„œ 풀이법을 λ°”λ‘œ 생각해낼 수 μžˆμ—ˆλ‹€.
  • 이 문제 μ—­μ‹œ Dynamic Programming을 μ΄μš©ν•΄μ„œ ν‘ΈλŠ” λ¬Έμ œμ˜€λ‹€.
    • dp[i] : i번째 μœ„μΉ˜κΉŒμ§€ νƒμƒ‰ν–ˆμ„ λ•Œ λ§ˆμ‹€ 수 μžˆλŠ” 포도주 μ–‘μ˜ μ΅œλŒ“κ°’μ„ μ €μž₯ν•œλ‹€.
  • μš°μ„ , λ§Œμ•½ n이 2 μ΄ν•˜λΌλ©΄ 3번 연속 λ§ˆμ‹€ 수 μ—†λ‹€λŠ” 쑰건에 ν•΄λ‹Ήν•  수 μ—†μœΌλ―€λ‘œ 무쑰건 포도주λ₯Ό λͺ¨λ‘ λ§ˆμ…”μ•Ό μ΅œλŒ“κ°’μ΄κΈ° λ•Œλ¬Έμ— 포도주 양을 λͺ¨λ‘ ν•©ν•˜κ³  좜λ ₯ν•œ λ’€ ν”„λ‘œκ·Έλž¨μ„ μ’…λ£Œν•œλ‹€.
  • n이 3 이상이라면 μš°μ„  1번과 2λ²ˆκΉŒμ§€ νƒμƒ‰ν–ˆμ„ λ•ŒλŠ” μœ„μ—μ„œ μ„€λͺ…ν•œ 바와 같이 μžˆλŠ” 포도주λ₯Ό λ‹€ λ§ˆμ‹œλŠ” κ²½μš°κ°€ μ΅œλŒ“κ°’μ΄κΈ° λ•Œλ¬Έμ— dp[1]=wine[1]κ³Ό dp[2]=wine[1]+wine[2]둜 μ΄ˆκΈ°ν™”ν•œλ‹€.
  • 3번째 μž”λΆ€ν„° for문으둜 λ°˜λ³΅ν•˜λ©΄μ„œ dp값을 μ±„μ›Œλ„£μ–΄μ£ΌλŠ”λ°, 총 μ„Έ κ°€μ§€ 경우λ₯Ό κ³ λ €ν•  수 μžˆλ‹€.
    • μ „μ „ 칸을 μ„ νƒν•˜μ§€ μ•Šκ³ , 이전 칸을 μ„ νƒν•˜λŠ” 경우 즉, μ—°μ†ν•΄μ„œ 두 μž”μ„ λ§ˆμ‹œλŠ” κ²½μš°μ΄λ‹€. (xoo)
      • 이 경우 dp[i-3]+wine[i-1]+wine[i]둜 ν‘œν˜„ν•  수 μžˆλ‹€.
    • 이전 칸을 μ„ νƒν•˜μ§€ μ•ŠλŠ” 경우 (oxo)
      • 이 경우 dp[i-2]+wine[i]둜 ν‘œν˜„ν•  수 μžˆλ‹€.
    • 그리고 ν˜„μž¬ μž”μ„ μ„ νƒν•˜μ§€ μ•ŠλŠ” 경우(oox)
      • 이 경우 dp[i-1]둜 ν‘œν˜„ν•  수 μžˆλ‹€.
    • 이 μ„Έ κ°€μ§€ 경우 쀑 κ°€μž₯ 큰 값을 dp[i] κ°’μœΌλ‘œ κ°±μ‹ ν•œλ‹€.
  • μ΄λŸ¬ν•œ 과정을 κ±°μ³μ„œ dp[n]에 μ €μž₯된 값이 nλ²ˆμ§ΈκΉŒμ§€ λ§ˆμ…¨μ„ λ•Œ 얻을 수 μžˆλŠ” μ΅œλŒ“κ°’μ΄λ―€λ‘œ dp[n]을 좜λ ₯ν•˜κ³  ν”„λ‘œκ·Έλž¨μ„ μ’…λ£Œν•œλ‹€.
import sys

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

if n<=2:
    print(sum(wine))
    sys.exit(0)

wine.insert(0,0)
dp=[0]*(n+1)
dp[1]=wine[1]
dp[2]=wine[1]+wine[2]
for idx in range(3,n+1):
    # ν˜„μž¬ μž”μ„ λ§ˆμ‹œλŠ” 경우의 μ΅œλŒ“κ°’
    drink=max(dp[idx-3]+wine[idx-1], dp[idx-2])+wine[idx]
    not_drink=dp[idx-1]
    dp[idx]=max(drink, not_drink)

print(dp[n])