🚩 해당 문제는 이분탐색을 활용하여 풀 수 있다.
이분탐색은 시작점 과 끝점을 설정하고 그 중간을 구하여 적절한 값을 찾아가는 방식이다.
시작점은 0 , 끝점은 문제에서 주어진 최대 값을 넣는것이 보통인데 해당 문제는 이렇게 풀면 안되는 문제여서 범위지정에 대해서 신중하게 생각을 해야한다.
🌘 문제 이해하기
- 강토는 자신의 기타 강의 동영상을 블루레이로 만들어 판매하려고 한다.
- 블루레이에는 총 N개의 강의가 들어가는데, 블루레이를 녹화할 때, 강의의 순서가 바뀌면 안 된다.
- 강토는 M개의 블루레이에 모든 기타 강의 동영상을 녹화하기로 했다.
- 때, 블루레이의 크기(녹화 가능한 길이)를 최소로 하려고 한다.
- M개의 블루레이는 모두 같은 크기이어야 한다.
🌗문제 자세히보기
- 한 블루레이의 크기를 이분탐색으로 구하는 것이다.
- 한 블루레이의 최소 하나의 강의를 꼭 녹화되어야 한다. 즉 블루레이의 최소 크기는 가장 긴 강의 길이 이다.
- 블루레이의 최대 크기는 모든 강의들 길이 합이다.
//최소는 right,최대는 left
//강의들
int[] arr = new int[n+1];
int left = 0;
int right = 0;
st = new StringTokenizer(br.readLine());
for(int i=1;i<=n;i++)
{
arr[i] = Integer.parseInt(st.nextToken());
left = Math.max(left, arr[i]); //가장 긴 강의 길이
right += arr[i]; //모든 강의 길이 합
}
이 범위만 잘 지정해주면 나머지는 쉽다.
1. 강의 수와 블루레이 수가 동일할 때
> 블루레이의 크기는 가장 긴 강의 길이가 된다. (각 블루레이의 모든 강의를 담아야 하기위해)
이분탐색 으로 임의로 구한 블루레이의 크기대로 강의들을 녹화 할때
2. 만들어진 총 블루레이의 개수가 만들고자 한 M개의 블루레이 개수보다 클 때
> 블루레이의 크기를 늘려야 한다. 크기를 늘려 블루레이의 개수 줄여야 한다.
3. 만들어진 총 블루레이의 개수가 만들고자 한 M개의 블루레이 개수보다 작을 때
> 블루레이의 크기를 줄여야 한다. 크기를 줄여 블루레이의 개수 늘려야 한다.
위의 방식들로 블루레이의 크기의 최소값을 구할때까지 이분탐색을 진행하면 된다.
🌕최종코드
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));
StringTokenizer st = new StringTokenizer(br.readLine());
//강의 수
int n = Integer.parseInt(st.nextToken());
//블루레이 수
int m = Integer.parseInt(st.nextToken());
//강의들
int[] arr = new int[n+1];
int left = 0;
int right = 0;
st = new StringTokenizer(br.readLine());
for(int i=1;i<=n;i++)
{
arr[i] = Integer.parseInt(st.nextToken());
left = Math.max(left, arr[i]);
right += arr[i];
}
//강의 수와 블루레이 수가 동일하다면 가장 긴 강의가 블루레이의 크기가 된다.
if(n == m)
{
Arrays.sort(arr);
System.out.println(arr[n]);
return;
}
int length = right;
while(left<=right)
{
ArrayList<Queue<Integer>> que = new ArrayList<>();
int mid = (left+right)/2;
int sum =0;
que.add(new LinkedList<>()); //블루레이 추가
int seq = 0;
for(int i=1;i<=n;i++)
{
//강의 추가
if(sum+arr[i] <=mid)
{
que.get(seq).add(arr[i]);
sum += arr[i];
}
else
{
seq++;
que.add(new LinkedList<>()); //블루레이 추가
que.get(seq).add(arr[i]);
sum = arr[i];
}
}
//블루레이 개수가 초과되면 블루레이 크기 다시 구하기
if(que.size()>m)
{
left = mid+1;
}
else
{ length = Math.min(length, mid);
right = mid-1;
}
}
System.out.println(length);
}
}
'항해' 카테고리의 다른 글
[DAY42] 99클럽 코딩테스트 JAVA 백준 DFS와 BFS 1260번 (1) | 2025.01.20 |
---|---|
[DAY41] 99클럽 코딩테스트 JAVA 백준 두 용색 2470번 (0) | 2025.01.17 |
[DAY39] 99클럽 코딩테스트 JAVA 백준 선분 위의 점 11663번 (1) | 2025.01.15 |
[DAY38] 99클럽 코딩테스트 JAVA 백준 랜선자르기 1654번 (0) | 2025.01.14 |
[DAY37] 99클럽 코딩테스트 JAVA 백준 암기왕 2776번 (시간초과 해결) (0) | 2025.01.13 |