https://www.acmicpc.net/problem/17951
문제
넓은 시험 범위와 어려운 과제로 유명한 '운영체제로 보는 데이터베이스시스템 알고리즘' 수업은 시험지가 너무 많아 실내에서는 시험을 치를 수 없어서 야외에서 시험을 진행한다. 해당 수업의 수강생인 현수는 오랜 시간에 걸쳐 풀 수 있는 모든 문제를 풀었고 제출만을 남겨두고 있었다. 그러나 갑자기 불어오는 강풍에 현수의 시험지가 모두 날아가 버렸고, 날아간 시험지를 줍는 동안 남은 시간을 다 써버리고 말았다.
시험지에 명시된 규칙 중에는 채점하는 조교의 편의를 위해 시험지를 반드시 순서대로 제출하라는 규칙이 있는데, 이 규칙 때문에 현수는 힘들게 치른 시험이 0점 처리될 위기에 빠지게 되었다!
그러나, 마음씨 좋은 조교인 주찬이는 평소 수업에 열심히 참여한 현수에게 한 번의 기회를 주기로 했다. 규칙은 규칙이므로 많은 점수를 줄 수는 없고, 시험지를 현재 순서 그대로 K개의 그룹으로 나눈 뒤 각각의 그룹에서 맞은 문제 개수의 합을 구하여 그 중 최솟값을 시험 점수로 하기로 하였다. 현수가 이번 시험에서 받을 수 있는 최대 점수를 계산하는 프로그램을 작성하자.
현수는 모르는 문제를 아예 풀지 않기 때문에 현수가 푼 문제는 모두 맞았다고 생각할 수 있으며, 조교는 마음씨가 좋아서 자신이 줄 수 있는 최대한의 점수를 준다.
입력
첫 번째 줄에 시험지의 개수 N과 시험지를 나눌 그룹의 수 K가 정수로 주어진다. (1 ≤ K ≤ N ≤ 10^5)
두 번째 줄에 각 시험지마다 맞은 문제의 개수 x가 정수로 주어진다 (0 ≤ x ≤ 20)
출력
현수가 받을 수 있는 최대 점수를 출력한다.
풀이
처음 해당 문제를 풀 때, 그룹을 나눌 때 연속적인 값이 아니라고 생각을 했다. 문제를 제대로 읽자!
1. 브루트포스로 접근하면 범위가 커서 엄청나게 시간을 초과하게 된다.
2. 매개변수 탐색
2-1) 왜 매개변수탐색으로 문제를 풀까
- 최대화, 최소화 문제, 탐색의 기준을 정하고 최적의 값을 찾는다.
- 값이 범위가 크고, 특정 값에 따라 만족 여부를 판변 가능.
- 즉 최종합을 최소 특정값이라고 할 때 몇 개의 그룹으로 만들 수 있을지 판별할 수 있다.
2-2) 매개변수 탐색 과정
K 그룹의 합이 최소가 X인 값을 찾아야 한다.
>> 그룹 합이 X 이상이고 그룹이 M개를 만족애햐 한다. 이 때의 X의 최솟값을 구해야 한다.
>> X 최솟값은 lower bound를 이용해 구하자
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
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 K = Integer.parseInt(st.nextToken());
int e = 0;
int s = 0;
st = new StringTokenizer(br.readLine());
int[] arr = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = Integer.parseInt(st.nextToken());
e += arr[i];
}
// 그룹의 합이 x 이상이 되고 그룹이 k개인 i를 찾는 바이너리 서치
// 연속 합이 x 이상.
// 그룹의 개수는 k 개
int val = 0;
while (s <= e) {
int mid = (s + e) / 2;
val = 0; // K 그룹의 각 합을 계산
int group = 0;
for (int i = 0; i < N; i++) {
val += arr[i];
if(val >= mid) {
group++;
val = 0;
}
}
if (group >= K) {
// group 감소시켜서 K가 되어야 함 -> mid 증가시켜야 함 -> s 증가
s = mid + 1;
} else {
// group 증가 시켜서 K가 되어야 함 -> mid 감소 -> e 감소
e = mid - 1;
}
}
System.out.println(e);
}
}
'CS > 알고리즘 풀이' 카테고리의 다른 글
[DP][백준 2225] 합분해 (0) | 2024.11.01 |
---|---|
[DP][백준 2293] 동전 1 (1) | 2024.11.01 |
[DP 0-1 knapsack][백준 2616] 소형기관차 (0) | 2024.10.30 |
[PrefixSum][백준 19951] 태상이의 훈련소 생활 (0) | 2024.10.30 |
[PrefixSum][백준 3020] 개똥벌레 (0) | 2024.10.26 |