[백준 2156번] 포도주 시식 - DP

2020. 10. 2. 06:53Algorithm

반응형

백준 2156번 동적 계획법(Dynamic Programming)으로 풀 수 있는 문제이다.

 

문제를 읽어보면,

포도잔의 개수가 N개 있고, 이를 선택하여 마실 수 있다. 그러나 조건이 있다.
연속해서 위치한 3잔을 모두 마실 수는 없다. 여기서 가장 많은 양의 포도주를 마실 수 있는 양은 얼마인지 구해야한다.

 

점화식을 생각하게 되었고, 이전에 풀어봤던 문제 유형이랑 비슷해서 방법을 떠올리는 건 쉽게할 수 있었다.

그러나, 하나 사소한 부분에서 실수로 return문을 적지 않아 '왜 틀렸지...'하며 시간을 조금 낭비했다.

 

DP로 풀기 위해선 점화식을 세우는게 중요한데,

우선 초기 조건을 잘 확인해서 풀어야한다.

 

N이 1, 2, 3일 때를 나누어서 초기 조건을 세웠다.

if (N == 1) {
    System.out.println(grapeAmount[0]);
    return;
} else if (N == 2) {
    System.out.println(grapeAmount[0] + grapeAmount[1]);
    return;
} else if (N == 3) {
    int max = Math.max(grapeAmount[0] + grapeAmount[1], grapeAmount[0] + grapeAmount[2]);
    max = Math.max(max, grapeAmount[1] + grapeAmount[2]);
    System.out.println(max);
    return;
}

나는 여기서 마지막 N==3일 때의 조건에 return을 실수로 안해놓고 계속 왜 틀렸지 헤맸다...

 

여기서 N이 3일 때의 조건을 잘 보면 문제의 점화식에 감이 올 것이다.

3가지의 경우가 존재한다. (연속된 3개의 포도주를 선택할 수 없기에 다음과 같은 조건이 나온다.)

 

1️⃣ 현재 포도주(i)를 선택하고 전전(i-2)의 포도주를 선택하는 경우

dp[i-2] + grapeAmount[i]

2️⃣ 현재 포도주(i), 전 포토주(i-1) 그리고 전전전 포도주(i-3)을 선택하는 경우

grapeAmount[i-1] + dp[i-3] + grapeAmount[i]

3️⃣ 현재 포도주를 선택하지 않는 경우

dp[i-1]

 

이렇게 3가지 조건의 점화식이 나오게 되고, 현재의 가장 큰 값을 찾기 위해 3가지 조건을 비교하며 갱신하면 된다.

 

전체 소스코드는,

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int N = Integer.parseInt(br.readLine());

        int[] grapeAmount = new int[N];

        for(int i = 0; i < N; i++) {
            grapeAmount[i] = Integer.parseInt(br.readLine());
        }

        if (N == 1) {
            System.out.println(grapeAmount[0]);
            return;
        } else if (N == 2) {
            System.out.println(grapeAmount[0] + grapeAmount[1]);
            return;
        } else if (N == 3) {
            int max = Math.max(grapeAmount[0] + grapeAmount[1], grapeAmount[0] + grapeAmount[2]);
            max = Math.max(max, grapeAmount[1] + grapeAmount[2]);
            System.out.println(max);
            return;
        }

        int[] dp = new int[N];
        dp[0] = grapeAmount[0];
        dp[1] = grapeAmount[0] + grapeAmount[1];
        int max = Math.max(grapeAmount[0] + grapeAmount[1], grapeAmount[0] + grapeAmount[2]);
        max = Math.max(max, grapeAmount[1] + grapeAmount[2]);
        dp[2] = max;

        for(int i = 3; i < N; i++) {
            int tempMax = Math.max(dp[i-2] + grapeAmount[i], grapeAmount[i-1] + dp[i-3] + grapeAmount[i]);
            dp[i] = Math.max(tempMax, dp[i-1]);
        }

        System.out.println(dp[N-1]);
    }
}
반응형

'Algorithm' 카테고리의 다른 글

[프로그래머스] 위장 - Hash  (0) 2020.10.08
[백준 2217번] 로프 - Greedy Algorithm  (0) 2020.10.04
[백준 1912번] 연속합 - DP  (0) 2020.09.30
[백준 14502번] 연구소 - BFS, DFS  (0) 2020.09.27
[백준 2178번] 미로탐색 - BFS  (0) 2020.09.26