알고리즘 공부💥/백준

[백준] 2156. 포도주 시식 / python

hyunsix 2021. 4. 22. 10:41

출처 : 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 이하의 음이 아닌 정수이다.

출력

첫째 줄에 최대로 마실 수 있는 포도주의 양을 출력한다.

예제 입력 1

6 6 10 13 9 8 1

예제 출력 1

33

 

 

Think Think 🔑

다이나믹 프로그래밍을 이용한 대표적인 유형이라고 할 수 있다. DP라고 하면 되게 거창해 보이지만 간단하게 말하면 '프로그램을 돌리면서 이미 계산된 결과는 별도의 다른 영역에 저장한 후 활용하여 중복된 계산을 하지 않도록' 하는 것이다. 피보나치수열 등의 점화식을 재귀로 표현할 때 시간복잡도를 낮추기 위해 사용된다.

 

피보나치처럼 이전의 판단에 근거하여 i번째 최대 와인섭취량을 구한다. 

 

0번째 = 0 ( 인덱스상 필요함 )

1번째에서 최대의 경우는 1번째 wine을 마시는 것
2번째에서 최대의 경우는 1번째, 2번째 wine을 모두 마시는 것

 

위의 전제를 기초하여 아래와 같이 i번째 와인에 대한 선택을 나눌 수 있다.

 

<i번째 wine에 대한 판단은 총 3가지로 분류할 수 있다.>

 

1) i번째 wine을 안 먹는 경우 -> 이 경우 [i-1]까지의 최대 와인섭취 결과를 그대로 이어간다.

2) i번째 wine을 먹고, i-1번째 와인은 안먹는 경우

   ->이 경우 [i-2]까지의 결과에 i번째 wine의 양을 더해준다.

3) i번째 wine을 먹고, i-1번째 와인도 먹은 경우

   -> 이 경우 [i-3]까지의 결과에 i번째 wine, i-1번째 wine의 양을 더해준다.

 

예제 입력을 통해서 축적된 결과를 출력해보면

 

인풋 : 6 6 10 13 9 8 1

출력 : [0, 6, 16, 23, 28, 33, 33]

 

출력 리스트에서 가장 마지막 값을 최종 출력하면 답을 얻을 수 있다. 

 

 

코드 구현 👀