문제
강토는 자신의 기타 강의 동영상을 블루레이로 만들어 판매하려고 한다. 블루레이에는 총 N개의 강의가 들어가는데, 블루레이를 녹화할 때, 강의의 순서가 바뀌면 안 된다. 순서가 뒤바뀌는 경우에는 강의의 흐름이 끊겨, 학생들이 대혼란에 빠질 수 있기 때문이다. 즉, i번 강의와 j번 강의를 같은 블루레이에 녹화하려면 i와 j 사이의 모든 강의도 같은 블루레이에 녹화해야 한다.
강토는 이 블루레이가 얼마나 팔릴지 아직 알 수 없기 때문에, 블루레이의 개수를 가급적 줄이려고 한다. 오랜 고민 끝에 강토는 M개의 블루레이에 모든 기타 강의 동영상을 녹화하기로 했다. 이때, 블루레이의 크기(녹화 가능한 길이)를 최소로 하려고 한다. 단, M개의 블루레이는 모두 같은 크기이어야 한다.
강토의 각 강의의 길이가 분 단위(자연수)로 주어진다. 이때, 가능한 블루레이의 크기 중 최소를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 강의의 수 N (1 ≤ N ≤ 100,000)과 M (1 ≤ M ≤ N)이 주어진다. 다음 줄에는 강토의 기타 강의의 길이가 강의 순서대로 분 단위로(자연수)로 주어진다. 각 강의의 길이는 10,000분을 넘지 않는다.
출력
첫째 줄에 가능한 블루레이 크기중 최소를 출력한다.
풀이
이분탐색 문제이다. (Parametric search)
9 3
1 2 3 4 5 6 7 8 9
블루레이의 크기를 인덱스로 생각하고 이분탐색을 하면 된다. 값은 강의의 수이다.
블루레이 크기를 기준으로 하면 강의의 수는 아래와 같은 배열이 나온다. (실제로 배열이 존재하진 않음)
9분 | 10분 | 11분 | 12분 | ... | 15분 | 16분 | 17분 |
6개 | 6개 | 5개 | 5개 | ... | 4개 | 4개 | 3개 |
위의 배열에서, 값이 3이 되는 순간을 lower bound를 이용해서 구하면 된다.
이때 가능한 블루레이의 크기는 가장 긴 강의의 길이~모든 강의의 총합이 된다.
예제로 치면 가장 긴 강의의 길이 = 9분, 모든 강의의 총합 = 45분이 된다.
블루레이의 수가 3개가 되는 첫 시점, 즉 lower bound를 구해주면 된다.
13분 | 14분 | 15분 | 16분 | 17분 | 18분 | ... | 27분 |
4개 | 4개 | 4개 | 4개 | 3개 | 3개 | ... | 2개 |
start = 9, end = 45, mid = 27
길이가 27분일 때 총 블루레이의 수 : 2개
3보다 작거나 같으므로 end = mid 해준다.
13분 | 14분 | 15분 | 16분 | 17분 | 18분 | ... | 27분 |
4개 | 4개 | 4개 | 4개 | 3개 | 3개 | ... | 2개 |
start = 9, end = 27, mid = 18
길이가 18분일 때 총 블루레이의 수 :3개
3보다 작거나 같으므로 end = mid 해준다.
13분 | 14분 | 15분 | 16분 | 17분 | 18분 | ... | 27분 |
4개 | 4개 | 4개 | 4개 | 3개 | 3개 | ... | 2개 |
start = 9, end = 18, mid = 13
길이가 13분일 때 총 블루레이의 수 : 5개
3보다 크므로 start = mid +1 해준다.
13분 | 14분 | 15분 | 16분 | 17분 | 18분 | ... | 27분 |
4개 | 4개 | 4개 | 4개 | 3개 | 3개 | 2개 |
start = 14, end = 18, mid = 16
길이가 16분일 때 총 블루레이의 수 : 4개
3보다 크므로 start = mid +1 해준다.
13분 | 14분 | 15분 | 16분 | 17분 | 18분 | ... | 27분 |
4개 | 4개 | 4개 | 4개 | 3개 | 3개 | 2개 |
start = 17, end = 18, mid = 17
길이가 17분일 때 총 블루레이의 수 : 3개
3보다 작거나 같으므로 end = mid 해준다.
start = 17, end = 17 이므로 반복을 종료한다.
이때 최종 start (또는 end)값이 블루레이의 길이가 된다.
이때 강의의 수는 아래와 같이 카운트 한다.
블루레이의 길이가 17분인 경우
남은 공간 : 17분
넣을 블루레이의 길이 : 1분
17분 >= 1분 이므로 넣을 수 있다. (현재 블루레이의 갯수 1개)
남은 공간 : 16분
넣을 블루레이의 길이 : 2분
16분 >= 2분 이므로 넣을 수 있다. (현재 블루레이의 갯수 1개)
남은 공간 : 14분
넣을 블루레이의 길이 : 3분
14분 >= 3분 이므로 넣을 수 있다. (현재 블루레이의 갯수 1개)
남은 공간 : 11분
넣을 블루레이의 길이 : 4분
11분 >= 4분 이므로 넣을 수 있다. (현재 블루레이의 갯수 1개)
남은 공간 : 7분
넣을 블루레이의 길이 : 5분
7분 >= 5분 이므로 넣을 수 있다. (현재 블루레이의 갯수 1개)
남은 공간 : 2분
넣을 블루레이의 길이 : 6분
2분 < 6분 이므로 넣을 수 없다.
블루레이의 갯수를 1개 올려주고, 블루레이의 길이를 17분으로 초기화해준다.
남은 공간 : 17분
넣을 블루레이의 길이 : 6분
17분 >= 6분 이므로 넣을 수 있다. (현재 블루레이의 갯수 2개)
남은 공간 : 11분
넣을 블루레이의 길이 : 7분
11분 >= 7분 이므로 넣을 수 있다. (현재 블루레이의 갯수 2개)
남은 공간 : 4분
넣을 블루레이의 길이 : 8분
4분 < 8분 이므로 넣을 수 없다.
블루레이의 갯수를 1개 올려주고, 블루레이의 길이를 17분으로 초기화해준다.
남은 공간 : 17분
넣을 블루레이의 길이 : 8분
17분 >= 8분 이므로 넣을 수 있다. (현재 블루레이의 갯수 3개)
남은 공간 : 9분
넣을 블루레이의 길이 : 9분
9분 >= 9분 이므로 넣을 수 있다. (현재 블루레이의 갯수 3개)
총 블루레이의 갯수는 3개가 된다.
코드
package baekjoon;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class BOJ2343 {
static int[] lectures;
static int N;
public static int lowerBound(int start, int end, int target) {
while (start < end){
int mid = (start + end) / 2;
if (getCount(mid) > target)
start = mid + 1;
else
end = mid;
}
return start;
}
private static int getCount(int mid) {
int count = 1;
int remain = mid;
for (int i = 0; i < N; i++) {
if (remain < lectures[i]) {
remain = mid;
count++;
}
remain -= lectures[i];
}
return count;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
lectures = new int[N];
int sum = 0;
int maxBlueray = 0;
for (int i = 0; i < N; i++) {
lectures[i] = Integer.parseInt(st.nextToken());
sum += lectures[i];
if (maxBlueray < lectures[i])
maxBlueray = lectures[i];
}
System.out.println(lowerBound(maxBlueray, sum, M));
}
}
결과
문제 | 결과 | 메모리 | 시간 | 언어 | 코드 길이 |
2343 | 맞았습니다!! | 22768 KB | 240 ms | Java 8 | 1530 B |
'알고리즘 > 자바' 카테고리의 다른 글
[JAVA] 백준 3665번 최종 순위 (0) | 2023.04.12 |
---|---|
[JAVA] 백준 2461번 대표 선수 (0) | 2023.02.24 |
[JAVA] 백준 1342번 행운의 문자열 (0) | 2023.02.08 |
[JAVA] 백준 1914번 하노이 탑 (0) | 2023.02.06 |