N개의 수가 주어질 때, 이 수열을 정확히 M개의 구간으로 나누려고 한다.
이때, 각 구간의 합 중 최댓값이 최소가 되도록 구간을 나누는 프로그램을 작성하라.
브루트포스 방식으로 1부터 가능한 최대값 범위(문제에서 10000까지)까지 반복하면서,
각 값 i를 "구간 합의 상한값(최댓값 후보)"라고 가정하고 아래 과정을 수행한다.
i를 넘으면 구간을 끊고, 새로운 구간을 시작한다.M 이하이고, 수 중 어떤 것도 i보다 큰 값이 없으면 정답 후보로 고려한다.이때 i가 가능한 후보 중 최소값이 되도록 계속 최소값을 갱신한다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[] nums = new int[n];
for (int i = 0; i < n; i++)
nums[i] = sc.nextInt();
int ans = 10000;
for (int i = 1; i <= 10000; i++) {
boolean isPassable = true;
int section = 1;
int cnt = 0;
for (int j = 0; j < n; j++) {
if (nums[j] > i) {
isPassable = false;
break;
}
if (cnt + nums[j] > i) {
cnt = 0;
section++;
}
cnt += nums[j];
}
if (isPassable && section <= m) {
ans = Math.min(ans, i);
}
}
System.out.println(ans);
}
}
1부터 가능한 최대값까지 순차적으로 구간 합의 상한을 늘려가며, 해당 값으로 M개 이하의 구간으로 나눌 수 있는지만 확인하고, 이를 통해
구간 합의 최대값의최솟값을 찾는다.
M개 이하로 나눌 수 있다면일부 구간을 쪼개정확히 M개로 만들 수 있으므로 정답 후보가 된다.
99C50 = 약 5 * 10^28개의 경우를 세야 한다.구간의 합의 최댓값을 결정한다면 구간을 몇 개로 나눠야 하는지 손쉽게 찾을 수 있다.M개 이하로 나눌 수 있는지를 확인하고, 그 중 가능한 최소값을 찾는다.M개로 나누는 것이지만, section <= M인 경우, 일부 구간(길이 ≥ 2)을 더 쪼개서 정확히 M개로 만드는 것이 가능하므로 정답 후보가 될 수 있다.i와 일치할 필요는 없으며,i부터 1씩 증가하며 탐색하므로, 최솟값으로 선택된 i는 반드시 어떤 구성에서 최대값과 일치하거나 가장 근접한 값이 된다.