일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- 시그널 핸들러
- 운영체제
- 코딩테스트 [ ALL IN ONE ]
- SDK
- 갤럭시 S24
- 네트워크
- 개발남노씨
- 인터럽트
- Extendable hashing
- B tree 데이터삽입
- 쉬운 코드
- 코딩애플
- 프로세스 주소 공간
- BreadcrumbsComputer-Networking_A-Top-Down-Approach
- 커널 동기화
- concurrency control
- 온디바이스AI
- recoverability
- 트랜잭션
- vite
- 김영한
- 시스템프로그래밍
- Git
- 백엔드
- CPU 스케줄링
- 운영체제와 정보기술의 원리
- 반효경
- 데이터베이스
- SQL
- 쉬운코드
- Today
- Total
티끌모아 태산
2156: 포도주 시식 본문
https://www.acmicpc.net/problem/2156
2156번: 포도주 시식
효주는 포도주 시식회에 갔다. 그 곳에 갔더니, 테이블 위에 다양한 포도주가 들어있는 포도주 잔이 일렬로 놓여 있었다. 효주는 포도주 시식을 하려고 하는데, 여기에는 다음과 같은 두 가지 규
www.acmicpc.net
설명
테이블 위에 다양한 포주가 들어있는 포도주 잔이 일렬로 놓여있다. 이를 시식하기 위해서 다음 두 가지 규칙이 있다.
- 포도주 잔을 선택하면 그 잔에 있는 포도주는 모두 마셔야하고, 마신 후에는 원래 위치에 다시 놓아야 한다.
- 연속으로 놓여 있는 3잔을 모두 마실 수는 없다.
최대한 많은 양의 포도주를 맛보기 원한다. 따라서 가장 많은 양의 포도주를 마실 수 있도록 하는 프로그램 작성.


예를들어, 6개의 포도주 잔이 있고, 각 잔에는 순서대로 6, 10, 13, 9, 8, 1 만큼의 포도주가 들어있다. 첫 번째, 두 번째, 네 번째, 다섯 번째 포도주 잔을 선택하면 총 포도주 양이 33으로 최대로 마실 수 있다.
핵심 아이디어
우선, 1부터 n까지의 번호가 붙어있는 n개의 잔이 있다, 그리고 각 잔의 양이 다르다. 최대한 많은 양을 먹을 수 있도록 하자. 가령, 6잔의 포도주 (6, 10, 13, 9, 8, 1) 가 있다고 했을 때, 마지막 포도주를 마실지 말지 결정하는 상황이라고 하자. 만약 내가 9,8을 먹었다면 마지막 잔을 먹을 수 없으며 13과9를 마신경우 마지막 잔인 1을 먹을 수 있다. 이때 가장 많이 먹을 수 있는 상황을 고르면 된다.
즉, 현재 포도주를 마실지 말지 결정 할 때는
- 현재 포도주와 이전 포도주를 마시고 전전 포도주는 먹지 않는다. (wine[i]+wine[i-1]+dp[i-3])
- 현재 포도주와 전전 포도주를 마시고 이전 포도주는 먹지 않는다. (wine[i]+dp[i-2])
- 현재 포도주를 마시지 않는다. (dp[i-1])
이렇게 3가지 경우로 나눠볼 수 있다. 3번 케이스에서 d[i-2] + wine[i-1]로 표기하지 않는 이유는 d[i-1]에 해당 케이스를 포함한 최댓값이 저장되어 있기 때문이다. 그리고 포도주 3잔 이하 경우에는 인덱스 에러 방지를 위해 예외처리를 먼저 해준다.
d[i]는 i번째 포도주까지 최대로 마신 포도주의 양이다.
- 전전(i-2)까지의 최대 양 + 현재 양 = (dp[n-2] + wine[i])
- 전전전(i-3)까지의 최대 양 + 전(i-1)번째 양 + 현재 양 = (dp[i-3] + wine[i-1] + wine[i])
- 전(i-1)까지의 최대 양 = dp[i-1]
세 가지 경우 더 큰 수를 dp에 저장하는 방식입니다.
코드 구현
# 포도주 잔 수 입력받기
n = int(input())
# 포도주 각 잔에 들어있는 양 입력받기
wine = [0] * 10001
for i in range(1, n+1):
wine[i] = int(input())
# dp 테이블 초기화
dp = [0] * 10001
dp[1] = wine[1]
dp[2] = wine[1] + wine[2]
# 3번째부터 3가지 경우 비교해서 최댓값을 dp에 저장한다
for i in range(1, n+1):
# 현재 잔을 먹지 않을 경우
# vs 현재 잔 + 이전 잔 먹기
# vs 현재 잔 + 전전 잔 먹기
dp[i] = max(dp[i-1], wine[i] + wine[i-1] + dp[i-3], wine[1] + dp[i-2])
print(max(dp))
'백준 문제 > DP' 카테고리의 다른 글
11052: 카드 구매하기 (0) | 2024.03.10 |
---|---|
1912: 연속합 (0) | 2024.03.10 |
2193: 이친수 (0) | 2024.03.10 |