백준 10468 숫자뽑기게임 - JAVA

2025. 4. 30. 21:29·알고리즘/백준

10468 문제 링크


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

 

문제 설명


 

입출력


 

코드


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
31
32
33
34
35
36
37
38
39
import java.io.*;
import java.util.*;
 
public class Main {
    static int[] arr;
    static int[][] dp;
    static int N;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String input;
        StringBuilder sb = new StringBuilder();
 
        while (!(input = br.readLine()).equals("0")) {
            StringTokenizer st = new StringTokenizer(input);
            N = Integer.parseInt(st.nextToken());
            arr = new int[N];
            for (int i = 0; i < N; i++) arr[i] = Integer.parseInt(st.nextToken());
 
            dp = new int[N][N];
            for (int[] row : dp) Arrays.fill(row, -1);
            sb.append(findMaxScore(0, N - 1)).append("\n");
        }
        System.out.print(sb);
    }
    // 구간 [s, e]에서 얻을 수 있는 최대 점수
    static int findMaxScore(int s, int e) {
        if (e - s <= 1) return 0; // 구간에 2개 이하만 남으면 더 이상 제거 불가
        if (dp[s][e] != -1) return dp[s][e];
 
        int max = 0;
        for (int i = s + 1; i < e; i++) {
            // 코드에서 첫 findMaxScore 진입이라면 탑다운 방식으로,
            // 마지막 점수의 합은 s + i + e일 것이다라고 가정하고 반대로 진행
            int score = arr[s] + arr[i] + arr[e];
            max = Math.max(max, findMaxScore(s, i) + findMaxScore(i, e) + score);
        }
        return dp[s][e] = max;
    }
}
Colored by Color Scripter
cs

 

알고리즘 설명


처음 접한 플래티넘 문제인데 생각보다 쉽게보여 빠르게 풀 수 있을줄 알았지만, 문제를 읽고선 DP 문제라는 것을 전혀 눈치채지 못하고, 반복문, DFS 등 여러 방법을 고민하다가 꽤 오랜 시간을 허비한 문제입니다. 결국 백준의 알고리즘 분류 버튼을 눌러 “다이나믹 프로그래밍” 문제라는 것을 알게 되었습니다.

또, 이 문제에 어떻게 DP를 적용하지? 라는 생각에 볼펜잉크와 메모지를 많이 써버렸네요. 문제를 많이 풀고 해당 문제가 어떤 풀이방식을 원하는지 보는 눈을 키워야 할 것 같습니다. 아직 많이 부족하다는 증거겠지요...

이 문제는, 현재 구간 [s, e]에서 맨 처음(s)와 맨 끝(e)는 제거가 불가능한 위치이므로, 가운데 숫자 i를 기준으로 양쪽 구간을 나누고, 양 끝과 가운데 숫자를 더한 값을 좌우 구간의 최댓값과 더해가며 구간의 최댓값을 갱신하는 방식입니다. 구간 내 숫자가 3개 이상일 때만 선택이 가능하므로 조건을 설정하고, 재귀적으로 분할하며 탐색을 반복합니다. 이 문제의 점화식 코드는 아래와 같습니다.

 

$$dp[s][e] = max(dp[s][i] + dp[i][e] + arr[s] + arr[i] + arr[e])$$

 

개인적으로 해당 문제는, 처음엔 점화식을 이해하지 못하더라도, 가능한 모든 구간 조합을 고려하면서 최댓값을 갱신한다는 흐름을 파악하면 조금씩 감이 잡히지 않을까 생각합니다.

 

코드 해석


DP 배열은 인덱스 s부터 e까지의 구간에서 얻을 수 있는 최대 점수를 저장하는 용도로 사용됩니다. 계산이 아직 이루어지지 않은 상태를 나타내기 위해 모든 값을 -1로 초기화합니다.

이후, 구간의 길이가 2 이하라면 세 수를 고를 수 없으므로 종료하는 기준으로, 재귀함수를 진행하고, 만약 이미 계산된 구간이라면 저장된 값을 그대로 반환합니다. 계산이 필요한 경우에는 s와 e 사이의 인덱스를 가운데로 삼아 구간을 (s, i)와 (i, e)로 나누고, 각각의 구간에서 얻을 수 있는 최대 점수에 현재 선택된 세 수 arr[s], arr[i], arr[e]의 합(score)을 더하여 최댓값을 갱신해 나갑니다.

계산이 종료되면, 함수의 반환값을 출력합니다.

'알고리즘 > 백준' 카테고리의 다른 글

백준 12015 가장 긴 증가하는 부분 수열 2 - JAVA  (2) 2025.06.06
백준 14500 테트로미노 - JAVA  (0) 2025.05.01
백준 6523 요세푸스 한 번 더! - JAVA  (0) 2025.04.01
백준 2143 두 배열의 합 - JAVA  (0) 2025.03.25
백준 2239 스도쿠 - JAVA  (0) 2025.03.24
'알고리즘/백준' 카테고리의 다른 글
  • 백준 12015 가장 긴 증가하는 부분 수열 2 - JAVA
  • 백준 14500 테트로미노 - JAVA
  • 백준 6523 요세푸스 한 번 더! - JAVA
  • 백준 2143 두 배열의 합 - JAVA
BIS's tech Blog
BIS's tech Blog
Welcome to Kanghyun's tech blog :)
  • BIS's tech Blog
    벼익숙의 기술 블로그
    BIS's tech Blog
  • 전체
    오늘
    어제
    • 분류 전체보기 (63) N
      • 알고리즘 (49) N
        • 백준 (40) N
        • 프로그래머스 (9)
      • CS 스터디 (14)
        • CS - JAVA (11)
        • CS - DB (3)
      • Spring (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • GitHub
  • 공지사항

  • 인기 글

  • 태그

    Lv2
    DFS
    프로그래머스
    bottom-up
    CS
    Baekjoon
    BFS
    기술질문
    알고리즘 고득점 kit
    브루트포스
    자료구조
    백준
    너비 우선 탐색
    Top-Down
    깊이 우선 탐색
    dp
    완전탐색
    java
    동적 계획
    재귀
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
BIS's tech Blog
백준 10468 숫자뽑기게임 - JAVA
상단으로

티스토리툴바