[백준 2805] 나무 자르기
사용 알고리즘 : 이분 탐색
📚 문제
🔗 문제 링크
📖 문제 설명
- 나무 M미터가 필요함
- 나무는 높이가 제각각
- 절단기에 높이 H를 지정하면 H미터 위의 나무를 모두 절단
- 적어도 M미터의 나무를 집에 가져가기 위한 절단기의 최대 높이 H를 구해야 함
🔍 입력 조건
- 첫째 줄에 나무의 수 N과 필요한 나무의 길이 M이 주어짐 (1 ≤ N ≤ 1,000,000, 1 ≤ M ≤ 2,000,000,000)
- 둘째 줄에 나무의 높이가 주어짐
- 나무의 높이의 합은 항상 M보다 크거나 같음
🔍 출력 조건
- 적어도 M미터의 나무를 집에 가져가기 위해서 절단기에 설정할 수 있는 높이의 최댓값을 출력
🧩 문제 분류
- 알고리즘: 이분 탐색
- 자료구조: 배열
- 난이도: Silver II
🚀 접근 방법
- 가능한 절단기 높이 범위를 설정 (0 ~ 나무 높이의 최댓값)
- 이분 탐색을 사용하여 최적의 높이를 찾음
- 각 높이로 잘랐을 때 얻을 수 있는 나무의 길이를 계산
- M미터 이상 얻을 수 있으면 높이를 늘리고, M미터 미만이면 높이를 줄임
💻 구현
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class BOJ2805 {
private static final int MAX_HEIGHT = 1000000000; // 문제에서 주어진 최대 높이
static int N, M;
static int[] trees;
// 이분 탐색
public static int cutTrees(int s, int e){
int answer = 0;
while (s <= e){
int mid = (s + e) / 2;
long sum = 0L;
for (int i = 0; i < trees.length; i++){
sum += Math.max(trees[i] - mid, 0);
}
if (sum < M) e = mid - 1;
else {
answer = mid;
s = mid + 1;
}
}
return answer;
}
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());
M = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
trees = new int[N];
for (int i = 0; i < N; i++){
trees[i] = Integer.parseInt(st.nextToken());
}
System.out.println(cutTrees(1, MAX_HEIGHT));
}
}
⏱ 시간 복잡도
- O(N log(max(trees)))
- 이분 탐색: O(log(max(trees)))
- 각 단계에서 모든 나무 확인: O(N)
💾 공간 복잡도
- O(N): 나무의 높이를 저장하는 배열의 크기
🧪 테스트 케이스
입력 | 출력 |
---|---|
4 7 20 15 10 17 | 15 |
📝 회고
- 나무의 높이와 잘린 나무의 길이 합이 int 범위를 초과할 수 있음.
- 1654 랜선 자르기 문제와 매우 유사하게 풀 수 있었다.
📚 참고 자료
없음