📜 코딩테스트/BAEKJOON\다이나믹 프로그래밍

백준 2156번 (DP) : 포도주 시식 (JAVA) 문제 풀이

2021. 8. 17. 15:57
목차
  1.  
  2. 1. 테이블 정의
  3.  
  4. 2. 점화식 찾기
  5.  
  6. 3. 초기값 설정
반응형

https://www.acmicpc.net/problem/2156

 

2156번: 포도주 시식

효주는 포도주 시식회에 갔다. 그 곳에 갔더니, 테이블 위에 다양한 포도주가 들어있는 포도주 잔이 일렬로 놓여 있었다. 효주는 포도주 시식을 하려고 하는데, 여기에는 다음과 같은 두 가지 규

www.acmicpc.net


 

✏️ 문제


 

🔐 문제 해결

나란히 놓여있는 포도주를 마셔서 가장 많이 마신 양을 출력하면 되는 문제입니다.

 

이 문제를 보면서 계단오르기 문제와 유사하여 해당 문제 풀이 방식대로 푼다면 틀리게 됩니다.

이번 문제에는 포도주를 마시지 않는 경우도 있을 수 있으므로, 해당 경우도 잘 생각해줘야 합니다.

 

문제에서 주어진 예제를 살펴보면, 가장 많이 마실 수 있는 방법은 아래와 같을 것입니다.

첫 번째, 두 번째, 네 번째, 다섯 번째를 선택하게 되면 33이 됩니다.

아래에서 정확한 풀이를 설명 해보겠습니다.

 

1. 테이블 정의

먼저 연속해서 3잔을 마실 수 없는 조건이 있으므로 2차원 배열이 필요합니다.

int[][] dp = new int[N][3];

테이블을 아래와 같이 세 가지로 생각해볼 수 있습니다.

  • dp[i][0]은 현재 i번째 포도주를 마시지 않은 상태를 뜻합니다.
  • dp[i][1]은 현재 i 번째 포도주를 마시고, i 번째 포도주를 포함해서 연속해서 1잔 마셨다는 뜻입니다.
  • dp[i][2]은 현재 i 번째 포도주를 마시고, i 번째 포도주를 포함해서 연속해서 2잔 마셨다는 뜻입니다.

 

2. 점화식 찾기

 

dp[i][0] 먼저 생각해보겠습니다.

  • 현재 i 번째 포도주를 마시지 않습니다.
  • 아래 세 가지 값 중 가장 큰 값을 찾아서 넣어주도록 합니다.
    • i-1 번째 포도주를 마시고, 연속해서 1잔을 마신 경우 : dp[i-1][1]
    • i-1 번째 포도주를 마시고, 연속해서 2잔을 마신 경우 : dp[i-1][2]

 

식으로 표현하면 아래와 같습니다.

dp[i][0] = Math.max(dp[i-1][1], dp[i-1][2]);

 

다음은 dp[i][1] 에 대해 생각해보겠습니다.

  • 현재 i 번째 포도주를 마셨고, 현재 포도주를 포함해서 연속으로 1잔을 마신 상태입니다.
  • 그렇다면 i-1 번째 포도주는 마시지 않았다는 뜻이 됩니다.
  • 아래 세 가지 값 중 가장 큰 값을 찾아서 넣어줍니다.
    • i-2 번째 포도주를 마시지 않은 경우 : dp[i-2][0]
    • i-2 번째 포도주를 마시고, 연속해서 1잔을 마신 경우 : dp[i-2][1]
    • i-2 번째 포도주를 마시고, 연속해서 2잔을 마신 경우 : dp\[i-2][2]

 

식으로 표현하면 아래와 같습니다.

// 2번째 전 포도주를 마시지 않았을 경우와, 연속해서 1잔 마셨을 경우와, 2잔 마셨을 경우의 최대값을 찾으면 됩니다.
dp[i][1] = Math.max( Math.max(dp[i-2][0], dp[i-2][1]) , dp[i-2][2] ) + arr[i];

 

dp[i][2]에 대해서는 아래와 같습니다.

  • 현재 i 번째 포도주를 마셨고, 현재 포도주를 포함해서 연속으로 2잔을 마신 상태입니다.
  • 그렇다는 얘기는, i-1 번째 포도주를 무조건 마셨다는 뜻이 됩니다.
  • 하지만, i-1 번째는 반드시 연속해서 1잔을 마신 상태이어야 합니다. (*중요)

 

식으로 표현하면 아래와 같습니다.

dp[i][2] = dp[i-1][1] + arr[i];

 

3. 초기값 설정

최대 i-2번째 까지 탐색하기 때문에 dp[2]까지 값을 설정 해주면 됩니다.

  • 1 번째 포도주
dp[1][0] = 0;
dp[1][1] = arr[1];
dp[1][2] = 0;
  • 2 번째 포도주
dp[2][0] = dp[1][1];
dp[2][1] = arr[2];
dp[2][2] = dp[1][1] + arr[2];

 


 

🗝 전체 코드

import java.util.*;
import java.io.*;

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

        int N = Integer.parseInt(bf.readLine());
        int[] arr = new int[N+1];
        int[][] dp = new int[N+1][3];

        for(int i=1; i<=N; i++) {
            arr[i] = Integer.parseInt(bf.readLine());
        }

        // init
        int MAX = arr[1];
        dp[1][0] = 0;
        dp[1][1] = arr[1];
        dp[1][2] = 0;

        // N이 1인 경우를 대비해 예외처리
        if(N >= 2) {
            dp[2][0] = dp[1][1];
            dp[2][1] = arr[2];
            dp[2][2] = dp[1][1] + arr[2];
            MAX = dp[2][2];
        }

        // dp
        for(int i=3; i<=N; i++) {
            // 현재 포도주를 마시지 않을 경우
            dp[i][0] = Math.max(dp[i-1][1], dp[i-1][2]);
            // 현재 포도주를 마시고, 연속으로 1잔만 마신 경우
            dp[i][1] = Math.max(Math.max(dp[i-2][1], dp[i-2][2]), dp[i-2][0]) + arr[i];
            // 현재 포도주를 마시고, 지금까지 연속해서 2잔 마신 경우
            dp[i][2] = dp[i-1][1] + arr[i];

            // 최댓값을 비교 후 넣어주도록 합니다.
            if(MAX < dp[i][0])  MAX = dp[i][0];
            if(MAX < dp[i][1])  MAX = dp[i][1];
            if(MAX < dp[i][2])  MAX = dp[i][2];
        }

        System.out.print(MAX);
    }
}
반응형
저작자표시 (새창열림)
  1.  
  2. 1. 테이블 정의
  3.  
  4. 2. 점화식 찾기
  5.  
  6. 3. 초기값 설정
'📜 코딩테스트/BAEKJOON\다이나믹 프로그래밍' 카테고리의 다른 글
  • 백준 10844번 (DP) - 쉬운 계단 수 (JAVA) 문제 풀이
  • 백준 11053번 (DP) - 가장 긴 증가하는 부분 수열 (JAVA) 문제 풀이
  • 백준 1003번(DP) - 피보나치 함수 (JAVA) 문제 풀이
  • 백준 2579번(DP) : 계단 오르기 (JAVA) 문제 풀이
iseunghan
iseunghan
꾸준하게 열심히..
iseunghan
iseunghan

공지사항

  • 어제보다 나은 오늘이 되기 위해 🔥
  • 분류 전체보기 (262)
    • 💐 Spring (14)
      • 개념 및 이해 (2)
      • Spring 핵심 기술 (24)
      • Spring REST API (8)
      • Spring MVC, DB 접근 기술 (7)
      • Spring Security (23)
      • Spring in Action (1)
    • 🌻 JAVA (84)
      • 자바 ORM 표준 JPA 프로그래밍 (20)
      • 알고리즘, 자료구조 (13)
      • 디자인 패턴 (7)
      • 정리정리정리 (43)
      • JUnit (1)
    • 🔖 Snippets (3)
      • Javascript (3)
    • ⚙️ Devops (22)
      • ⛏ Git (11)
      • 🐳 Docker (6)
      • 🐧 Linux (3)
      • 🌈 Jenkins (1)
      • 📬 Kafka (1)
    • 💬 ETC.. (4)
      • 💻 macOS (2)
    • 🌧️ ORM (2)
      • JPA (2)
    • 🐍 Python (3)
    • 📚 Databases (15)
      • 오라클로 배우는 데이터베이스 개론과 실습(2판) (3)
      • RealMySQL 8.0 (8)
    • 🔥 Computer Science (5)
      • 📡 네트워크 (5)
    • 🏷️ 협업 (1)
    • 📜 코딩테스트 (38)
      • BAEKJOON\수학 1, 수학 2 (8)
      • BAEKJOON\재귀 (5)
      • BAEKJOON\브루트 포스 (3)
      • BAEKJOON\정렬 (1)
      • BAEKJOON\백트래킹 (5)
      • BAEKJOON\BFS, DFS (6)
      • BAEKJOON\이분탐색 (1)
      • BAEKJOON\다이나믹 프로그래밍 (9)
      • BAEKJOON\그리디 알고리즘 (0)
    • ✨ ISEUNGHAN (1)

인기 글

최근 글

전체
오늘
어제
반응형
hELLO · Designed By 정상우.
iseunghan
백준 2156번 (DP) : 포도주 시식 (JAVA) 문제 풀이
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.