문제 : https://www.acmicpc.net/problem/2156
n개의 포도주 잔과 각 포도주 잔에 들어있는 포도주의 양이 주어졌을 때,
가장 많은 양의 포도주를 마실 수 있게 구하는 문제.
import sys
input = sys.stdin.readline
N = int(input()) # 포도주 개수
wine = [0]*(N+1)
dp = [0]*(N+1)
# 포도주 입력받기
for i in range(1, N+1):
wine[i] = (int(input())) # 입력받은 포도주를 추가
# 최대로 마실 수 있는 포도주의 양 출력
dp[1] = wine[1]
if(N >= 2):
dp[2] = wine[1] + wine[2]
for i in range(3, N+1):
# 1. 현재 잔 선택 x, 이전의 연속된 2잔
wine1 = dp[i-1]
# 2. 현재 먹는잔+이전의 잔 이렇게 연속된 2개 선택
wine2 = dp[i-3]+wine[i]+wine[i-1]
# 3. 현재 먹는잔+한칸 띄어 먹는 잔
wine3 = dp[i-2]+wine[i]
dp[i] = max(wine1, wine2, wine3) # 가장 최대가 되는 잔 선택
print(dp[N])
[문제풀이]
1. 포도주 잔을 선택하면 그 잔에 들어있는 포도주는 모두 마셔야 하고, 마신 후에는 원래 위치에 다시 놓아야 한다.
2. 연속으로 놓여 있는 3잔을 모두 마실 수는 없다.
이 두개의 규칙에 따라 문제를 풀기 위한 점화식을 세워야 한다.
우선, 규칙에 따라 이 문제를 풀기 위한 방법은 이렇다.
이전에 구한 포도주의 최댓값들의 누적합에서, 포도주가 새로 들어올 경우엔 연속 세잔을 먹지 않고 최대로 먹는 경우는 이 세가지다.
이 규칙에 따라 포도주의 최댓값을 구하는 예시를 들어보자.
\
여기서 DP[i-1]의 최댓값은 3잔 연속 선택 불가로 8L와 9L가 들고 있는 잔 2개를 선택하는 경우다.
그래서 현재 잔을 선택하지 않고 이전의 잔을 선택하는 경우와, 현재 잔 -2 잔을 선택하지 않고 나머지 잔을 선택하는 경우, 그리고 현재 잔 바로 이전의 잔을 선택하지 않는 이 세가지 경우 중 최댓값을 선택하면 누적 최대 잔을 구할 수 있다.
이를 점화식으로 만들면 이렇게 된다.
# 1. 현재 잔 선택 x, 이전의 연속된 2잔
wine1 = dp[i-1]
# 2. 현재 먹는잔+이전의 잔 이렇게 연속된 2개 선택
wine2 = dp[i-3]+wine[i]+wine[i-1]
# 3. 현재 먹는잔+한칸 띄어 먹는 잔
wine3 = dp[i-2]+wine[i]
dp[i] = max(wine1, wine2, wine3) # 가장 최대가 되는 잔 선택
이 점화식을 이용해 문제의 누적 최대 포도주의 값을 구하면 마지막 N번째가 N잔의 포도주가 들어왔을 때 최대로 먹을 수 있는 값이다!
'코딩테스트 > 백준' 카테고리의 다른 글
| [백준] 1463번 : 1로 만들기 (Python) (0) | 2024.12.27 |
|---|---|
| [백준] 1197번 : 최소 스패닝 트리 (Python) (0) | 2024.12.27 |
| [백준] 11653번 : 소인수분해 (Python) (0) | 2024.12.27 |
| [백준] 11576번 : Base Conversion (Python) (1) | 2024.12.27 |
| [백준] 2745번 : 진법 변환 (Python) (2) | 2024.12.27 |