백준 2512 - 예산
Updated:
Java
2512 번 - 예산
문제
접근 방법
단순하게 반복문으로 해결이 가능하지만, 이분 탐색을 사용하여 시간을 단축하는 문제이다.
반복문으로 해결 할 시, 상한액을 1부터 예산 최대까지 기준값이 예산 내에 충족하는지 확인한다.
따라서 시간 복잡도는 예산 중 최대액을 k라고 할 시,
O(n * k) 이며, O(n^2) 이다.
이진 탐색을 사용 할 시, 1부터 예산 최대까지 탐색을 단축 할 수 있다.
시간 복잡도는 O(n * log(k)) 이며, O(nlogn) 이다.
코드
import java.util.*;
import java.io.*;
public class Main {
static int n, result, m, biggest;
static int[] arr;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stk;
n = stoi(br.readLine());
arr = new int[n];
stk = new StringTokenizer(br.readLine());
for(int i = 0; i < n; i++) {
arr[i] = stoi(stk.nextToken());
biggest = Math.max(arr[i], biggest);
}
m = stoi(br.readLine());
// 이분탐색 시작
binarySearch(1, biggest);
/* 단순 반복문으로 해결
for(int i = 1; i <= biggest; i++) {
if(cal(i) == 0) {
result = i;
}
}
*/
System.out.println(result);
br.close();
}
private static void binarySearch(int low, int high) {
int mid;
if(low <= high) {
mid = (low + high) / 2;
int rt = cal(mid);
// 예산 분배시, 분배 금액이 예산 내에 들어오면
if(rt == 0) {
result = mid;
// 기준을 올린다.
binarySearch(mid + 1, high);
}
// 예산이 더 크면, 기준을 내린다.
else if(rt == 1) {
binarySearch(low, mid - 1);
}
}
}
private static int cal(int curN) {
int sum = 0;
for(int i = 0; i < n; i++) {
if(arr[i] <= curN) {
sum += arr[i];
}
else {
sum += curN;
}
}
// 예산 분배시, 분배 금액이 예산 내에 들어오면
if(sum <= m) {
return 0;
}
// 분배 금액이 예산보다 클 시, 기준을 낮춘다.
else {
return 1;
}
}
static int stoi(String str) {
return Integer.parseInt(str);
}
}