코딩테스트/BOJ

[BOJ] 2343 기타 레슨 - JAVA

5월._. 2023. 4. 21.
728x90

1. 문제

 

2343번: 기타 레슨

강토는 자신의 기타 강의 동영상을 블루레이로 만들어 판매하려고 한다. 블루레이에는 총 N개의 강의가 들어가는데, 블루레이를 녹화할 때, 강의의 순서가 바뀌면 안 된다. 순서가 뒤바뀌는 경

www.acmicpc.net

강토는 자신의 기타 강의 동영상을 블루레이로 만들어 판매하려고 한다. 블루레이에는 총 N개의 강의가 들어가는데, 블루레이를 녹화할 때, 강의의 순서가 바뀌면 안 된다. 순서가 뒤바뀌는 경우에는 강의의 흐름이 끊겨, 학생들이 대혼란에 빠질 수 있기 때문이다. 즉, i번 강의와 j번 강의를 같은 블루레이에 녹화하려면 i와 j 사이의 모든 강의도 같은 블루레이에 녹화해야 한다.

강토는 이 블루레이가 얼마나 팔릴지 아직 알 수 없기 때문에, 블루레이의 개수를 가급적 줄이려고 한다. 오랜 고민 끝에 강토는 M개의 블루레이에 모든 기타 강의 동영상을 녹화하기로 했다. 이때, 블루레이의 크기(녹화 가능한 길이)를 최소로 하려고 한다. 단, M개의 블루레이는 모두 같은 크기이어야 한다.

강토의 각 강의의 길이가 분 단위(자연수)로 주어진다. 이때, 가능한 블루레이의 크기 중 최소를 구하는 프로그램을 작성하시오.


2. 풀이

1.  이분탐색으로 진행했다. 강의의 길이를 입력받으면서 이분탐색에서 사용할 min, max값을 구한다.

1-1.  min값은 한 강의의 최대 길이다. 한 블루레이에는 한 강의 이상 들어가야하기 때문에 아무리 블루레이의 용량을 줄여도 강의 길이만큼은 확보되어야 한다.

1-2.  max값은 모든 강의의 합 +1로 설정했다. +1한 건 혹시나의 경우를 위해 넉넉히 잡은 것이다. 

2.  mid=(min+max)/2 값을 이용해서 용량을 탐색한다.

3.  모든 강의가 한 블루레이에 있다고 생각하고 초기값을 count = 1로 한다. 

4.  sum은 강의 길이를 누적합시키면서 mid를 넘기는지 체크하는 용도다. 처음에는 0으로 둔다.

5.  sum에 현재 강의 길이를 합친 뒤 그 값이 mid를 넘긴다면 'sum=현재강의 길이' 로 만든 후 count++한다. 이전까지의 강의를 한 블루레이에 담고 이번 강의부터 새 블루레이에 담는다는 의미다.

6.  만약 count(=블루레이 수)가 M보다 크다면 용량을 더 올려야 한다. 따라서 min = mid+1한다. 

7.  만약 count가 M보다 같거나 작다면 용량을 줄여도 된다. max = mid-1한다.

8.  min<=max일 때 2~7을 반복하고, 마지막에 min을 출력한다.

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

public class BOJ_2343_기타레슨 {
   public static void main(String[] args) throws IOException {
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      StringTokenizer st = new StringTokenizer(in.readLine());
      int N = Integer.parseInt(st.nextToken());
      int M = Integer.parseInt(st.nextToken());

      int[] lec = new int[N];
      int min = 1, max = 1;//min : 원소 중 최댓값, max : 모든 원소의 합
      st = new StringTokenizer(in.readLine());
      for (int i = 0; i < N; i++) {
         lec[i] = Integer.parseInt(st.nextToken());
         max += lec[i];
         min = Math.max(min,lec[i]);
      }

      int mid, sum, count;
      while(min<=max){
         mid = (min+max)/2;
         count = 1;
         sum = 0;
         for(int l:lec){
            sum += l;
            if(sum > mid){
               sum = l;
               count++;
            }
         }

         if(count>M){
            min = mid+1;
         }else{
            max = mid-1;
         }
      }

      System.out.println(min);
   }
}

3. 결과

타입문제인줄 알고 int->long으로 바꿔서 테스트해봤지만 틀렸다. (어쩐지 이상하다고 생각했다. 이미 int로 가능한 지 확인했었는데 ;_;)

원인은 min값에 있었다. 한 블루레이에는 한 강의 이상 들어가야하기 때문에 min값이 한 강의의 최대 길이가 되어야 한다.

'코딩테스트 > BOJ' 카테고리의 다른 글

[BOJ] 5014 스타트링크 - JAVA  (1) 2023.04.23
[BOJ] 10025 게으른 백곰 - JAVA  (0) 2023.04.22
[BOJ] 17266 어두운 굴다리 - JAVA  (0) 2023.04.20
[BOJ] 2725 보이는 점의 개수 - JAVA  (0) 2023.04.19
[BOJ] 1913 달팽이 - JAVA  (0) 2023.04.15

댓글