코딩 테스트/백준
[Python] 백준 2156 포도주 시식
위시리
2025. 3. 19. 10:47
문제 분석
- 다양한 포도주가 들어있는 포도주 잔이 일렬로 놓여 있다.
- 포도주 잔을 선택하면 그 잔에 들어있는 포도주는 모두 마셔야 하고 마신 후에는 원래 위치에 다시 놓아야 한다.
(한 번 마신 포도주는 채워지지 않는다. → 방문체크) - 연속으로 놓여있는 3잔을 모두 마실 수 없다.
- 포도주 잔을 선택하면 그 잔에 들어있는 포도주는 모두 마셔야 하고 마신 후에는 원래 위치에 다시 놓아야 한다.
- 최대한 많은 포도주 맛을 보기 위해 어떤 포도주 잔을 선택해야 할지 고민
- 1 ~ n 번호의 n개의 포도주잔이 테이블 위에 순서대로 있음
- 가장 많은 양의 포도주를 마실 수 있도록 하는 프로그램
코드 설계
- 이전 단계에서 탐색한 최댓값을 토대로 다음 단계까지 탐색한 최댓값을 구할 수 있다.
- i번째 포도주까지 탐색했을 때 마실 수 있는 최대 양은?
- i번째 포도주를 마시는 경우
- 연속으로 3잔을 마실 수 없다는 조건
- 1-1) 이전 포도주는 마시고, 전전 포도주는 마시지 않은 경우
i-3번째까지 탐색했을 때 마실수 있는 최대의 양 + i-1번째 포도주의 양 + i번째 포도주의 양
dp[ i-3 ] + arr[ i-1 ] + arr [ i ] - 1-2) 이전 포도주는 마시지 않고, 전전 포도주는 마신 경우
i-3번째까지 탐색했을 때 마실수 있는 최대의 양 + i-2번째 포도주의 양 + i번째 포도주의 양
dp[ i-3 ] + arr[ i-2 ] + arr[ i ]
dp[ i-2 ] + arr[ i ]
- i번째 포도주를 마시지 않는 경우
- 이전 포도주와 전전 포도주를 마심
dp[ i-1 ] + dp[ i-2 ] + arr[ i ]
i-1번째까지의 포도주를 탐색했을 때 마실 수 있는 포도주의 최대 양 : dp[ i-1 ] - 왜 마시지 않는 경우도 체크해야 하는가? (https://www.acmicpc.net/board/view/60664)
- dp[n]은 n번째 와인까지 따졌을 때 마실 수 있는 와인의 최대 양이다. 이는,
- 전전(n-2)까지의 최대 양 + 현재 양
- 전전전(n-3)까지의 최대양 + 전(n-1)번째 양 + 현재양
- 두 가지 경우 중 더 큰 수를 dp에 저장하는 방식이다.
- 최종 저장된 dp 값을 살펴보면 [6 16 23 28 33 32]
- 이때 dp[6]에 33이 아닌 32가 저장된 이유는 현재(n) 와인을 마시지 않은 경우를 고려하지 않았기 때문
- dp[n-1]에 해당하는 값과 비교하지 않았기 때문이다.
- 이전 포도주와 전전 포도주를 마심
- i번째 포도주를 마시는 경우
정답 코드
실패
import sys
input = sys.stdin.readline
n = int(input())
arr = []
for _ in range(n) :
arr.append(int(input()))
if n < 3 :
print(sum(arr))
else :
dp = [0] * (n+1)
dp[0] = arr[0]
dp[1] = arr[0] + arr[1]
for i in range(2, n+1) :
dp[i] = max(dp[i-2], (dp[i-3] + arr[i-1])) + arr[i]
print(dp[n])
정답 코드
import sys
input = sys.stdin.readline
n = int(input())
wine = []
for _ in range(n) :
wine.append(int(input()))
dp = [0 for _ in range(n)]
dp[0] = wine[0]
if n > 1 : # 최소 2잔 있음
dp[1] = wine[0] + wine[1]
if n > 2 : # 최소 3잔 있음
# 전전 + 현재 : w[0] + w[2]
# 전 + 현재 : w[1] + w[2]
# 전전 + 전 : w[0] + w[1]
dp[2] = max((wine[0] + wine[2]) , (wine[1] + wine[2]), dp[1])
for i in range(3, n) :
# 1. 현재의 잔을 마시는 경우
# 1-1. 전전 마시고, 전 안마심 : dp[i-2] + wine[i]
# 1-2. 전전 안마시고, 전 마심 : dp[i-3] + wine[i-1] + wine[i]
# 2. 현재 잔을 안마시는 경우 : dp[i-1]
dp[i] = max((dp[i-2] + wine[i]), (dp[i-3] + wine[i-1] + wine[i]), dp[i-1])
print(dp[n-1])
2회차 - 25.03.21
import sys
input = sys.stdin.readline
n = int(input())
wine = [int(input()) for _ in range(n)]
dp = [0 for _ in range(n)]
dp[0] = wine[0]
if n > 1 :
dp[1] = wine[0] + wine[1] # 당연히 다 마셔야..
if n > 2 : # 최소 3잔이면, 연속되지 않게 경우의 수 체크
# 3번째 잔에 대해
# o x o
# x o o
# o o x
dp[2] = max((wine[0] + wine[2]), (wine[1] + wine[2]), dp[1])
# o o x o
# o x o o
# ? o o x
for i in range(3, n) :
dp[i] = max((dp[i-2]+wine[i]), (dp[i-3]+wine[i-1]+wine[i]), dp[i-1])
# print(dp)
print(dp[n-1])