문제
https://www.acmicpc.net/problem/2805
문제 접근
- $N$과 $M$이 매우 크기 때문에 일반적인 완전탐색 알고리즘으로는 해결할 수 없다. 따라서 다른 방식을 찾아야 한다.
- 적어도 $O(logN)$이 되어야 할 것이다.
- 적어도 M미터의 나무를 가져가야 하는데 목재 절단기의 높이 $H$를 이분 탐색으로 확인할 수 있다. 가져가려하는 나무의 길이 M은 모든 나무의 높이 합까지 될 수 있기 때문에 절단기가 가질 수 있는 높이는 0부터 시작해야 한다.
- 또한 절단기의 높이의 상한선은 나무들의 모임 중 가장 큰 나무의 높이가 될 것이다. 따라서 절단기의 높이 범위는 $0 \leq H \leq \max(tree)$가 될 것이다.
- 목재의 계산은 문제에 제시된 대로 따라하면 구할 수 있다. 이때 목재가 목표량 $M$보다 크거나 같다면 더 높은 위치에서 잘라도 목재가 $M$이 될 수 있기 때문에 하한을 높이면 된다. 그 반대라면 더 낮은 높이에서 잘라야 하므로 상한을 낮추면 된다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
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[] trees = new int[N];
long start = 0;
long end = 0;
st = new StringTokenizer(br.readLine());
for (int i = 0; i < N; i++){
trees[i] = Integer.parseInt(st.nextToken());
end = Math.max(end, trees[i]);
}
while(start < end){
long mid = (start + end) / 2;
if (cut(mid, trees) >= M){
start = mid + 1;
} else{
end = mid;
}
}
System.out.println(start - 1);
}
public static long cut(long cutHeight, int[] trees){
long cnt = 0;
for (int tree : trees) {
if (tree > cutHeight) {
cnt += tree - cutHeight;
}
}
return cnt;
}
}
- 해당 문제 유형은 upper bound, lower bound로 대표되는 이분 탐색의 상계, 하계를 묻는 유형인데 아직 이해가 잘 되지 않아 추가적으로 공부가 필요하다.
'Algorithm > BinarySearch' 카테고리의 다른 글
[백준][BOJ 2343] - 기타 레슨 (2) | 2023.10.10 |
---|---|
[백준][BOJ 17266] - 어두운 굴다리 (1) | 2023.10.05 |
BOJ 2110 - 공유기 설치 문제 (0) | 2023.03.25 |
이분 탐색의 원리와 구현 방법 (0) | 2023.03.16 |