image.png

코드 (1차적으로 생각한 풀이)

package day5.B2343;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

import static java.lang.Integer.MAX_VALUE;

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

        int lesson = Integer.parseInt(st.nextToken());
        int bluelay = Integer.parseInt(st.nextToken()); // 두 값 입력받고
        int[] a = new int[lesson];

        st = new StringTokenizer(br.readLine()); // 줄바꿈 하고
        for(int i = 0; i < lesson; i++){
            a[i] = Integer.parseInt(st.nextToken());
        } // 배열까지 입력받음

        // 1. 일단 정렬
        Arrays.sort(a);

        // 2. bluelay로 나눠야 해.
        int[] bluelaycount = new int[bluelay];

        bluelaycount[0] = lesson; // 처음에 초기화 (n, 0, 0, 0 ...)

        for(int i = 0; i < bluelay; i++){
            int max = MAX_VALUE;
            if(bluelaycount[i] > max) {
                max = bluelaycount[i];
            }
        } // 이렇게 하면 배열을 돌면서, 합의 최댓값 찾음.

        // 3. 이 최댓값들 중, 최솟값을 찾아야 합니다.
        bluelaycount[0] = lesson - 1;
        bluelaycount[1] = 1;
        for(int i = 0; i < bluelay; i++){
            int max = MAX_VALUE;
            if(bluelaycount[i] > max) {
                max = bluelaycount[i];
            }
        }

        // 나중에 이들 중 min을 찾아.

    }
}

이 코드가 구현하기 힘들고 틀린 이유

  1. 이미 문제 조건에 “2번째 줄에 강토의 기타 레슨의 길이가 레슨 순서대로 주어진다.” 고 했으므로 Arrays.sort() 를 쓸 필요가 없음
  2. (n, 0, 0,0..)인데, 그러면 모든 경우의 수를 다 해봐야하나? 그럴 순 없음.

정답 코드

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

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

        // 1. 입력
        StringTokenizer st = new StringTokenizer(br.readLine());
        int n = Integer.parseInt(st.nextToken()); // 강의 수
        int m = Integer.parseInt(st.nextToken()); // 블루레이 수
        int[] lessons = new int[n];

        st = new StringTokenizer(br.readLine());
        int max = 0, sum = 0;
        for (int i = 0; i < n; i++) {
            lessons[i] = Integer.parseInt(st.nextToken());
            max = Math.max(max, lessons[i]); // 가장 긴 강의
            sum += lessons[i]; // 전체 합
        }

        // 2. 이분 탐색
        int left = max;
        int right = sum;
        int answer = sum;

        while (left <= right) {
            int mid = (left + right) / 2;

            // mid 용량으로 블루레이 몇 개 필요한지 계산
            int count = getRequiredBluRays(lessons, mid);

            if (count <= m) {
                // 가능한 경우, 더 줄일 수도 있음
                answer = mid;
                right = mid - 1;
            } else {
                // 용량이 너무 작다 → 더 늘려야 함
                left = mid + 1;
            }
        }

        System.out.println(answer);
    }

    // 📦 mid 크기로 나눌 때 필요한 블루레이 개수 세기
    public static int getRequiredBluRays(int[] arr, int maxSize) {
        int count = 1; // 블루레이 개수
        int sum = 0;

        for (int i = 0; i < arr.length; i++) {
            if (sum + arr[i] > maxSize) {
                count++;
                sum = arr[i]; // 새로운 블루레이 시작
            } else {
                sum += arr[i];
            }
        }

        return count;
    }
}

이 문제의 핵심

가능한 블루레이 용량(합) 이 그 대상.

그 용량을 연속적으로 묶어서 합친 값들 중에서 최솟값을 찾는 것