ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] 백준 2805 나무 자르기
    Programming/Algorithm 2021. 3. 3. 00:16

     

    문제

    필요한 나무의 길이 M과 나무들의 높이가 주어진다.

    절단기 높이 H를 지정하여 나무들을 자르고, 잘라진 부분이 M 이상이 되게 만드는 H의 최댓값을 구하는 문제이다.

     

    - 1 <= N(나무 수) <= 1,000,000(백만)

    - 1 <= M(필요한 나무 길이) <= 2,000,000,000 (20억)

    - 0 <= 나무들의 높이 <= 1,000,000,000(10억)

     

    이 때 주의할 점은 나무높이의 최대값이 10억일 수 있다는 것이다.

    선형탐색을 이용한다면 10억부터 1씩 감소시키며 연산을 해야 하는데, 이럴 경우 시간 제한(1초)안에 풀이할 수 없다.

     

    이 문제는 이진탐색을 이용하여 해결할 수 있다.

    탐색 범위를 1/2로 줄여가며 탐색한다면 시간 제한안에 H의 최댓값을 구할 수 있게 된다.

     

     

    풀이

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.Arrays;
    import java.util.StringTokenizer;
    
    public class Main {
    
        // 선형탐색은 시간초과
        static void wrongAnswer() 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());
    
            st = new StringTokenizer(br.readLine());
            int[] trees = new int[N];
            for (int i = 0; i < N; i++) {
                trees[i] = Integer.parseInt(st.nextToken());
            }
    
            int max_height = Arrays.stream(trees).max().getAsInt(); // 10억이 될 수 있기 때문
            while (true) {
                long cnt = 0;
                for (int t : trees) {
                    cnt += Math.max((t - max_height), 0);
                }
                if (cnt >= M) break;
                max_height--;
            }
    
            System.out.println(max_height);
        }
    
        // 540ms
        static void solution() 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());
    
            st = new StringTokenizer(br.readLine());
            long low = 0, high = 0;
            int[] trees = new int[N];
            for (int i = 0; i < N; i++) {
                trees[i] = Integer.parseInt(st.nextToken());
                high = high < trees[i] ? trees[i] : high;
            }
    
            while (low <= high) {
                long mid = (low + high) / 2;
    
                long cut = 0;
                for (int t : trees) {
                    cut += Math.max(t - mid, 0);
                }
    
                if (cut >= M) {
                    low = mid + 1;
                } else {
                    high = mid - 1;
                }
            }
            System.out.println(high);
        }
    
        public static void main(String[] args) throws IOException {
            solution();
        }
    }
    

     

     

    채점결과

     

    댓글

Designed by black7375.