ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] 백준 2110 공유기 설치
    Programming/Algorithm 2021. 3. 3. 20:57

     

    문제

    집 N개에 공유기 C개를 설치한다.

    공유기가 설치된 거리가 가장 가까운 두 집을 골라 두 집의 거리 차를 구한 뒤에

    거리의 차이가 최대가 되는 경우의 거리차를 출력하는 문제이다.

     

    1) 브루트포스 방식 (X)

    문제를 곧이곧대로 생각한다면 다음과 같이 풀이할 수 있다.

    - N개의 집 중 공유기를 설치할 C개를 고른다 => nCc (조합)

    - 모든 경우의 수에서 가장 인접한 집 2채의 거리차를 구하여 거리차의 최댓값을 리턴한다.

    하지만 N과 C 범위의 최댓값(N:20만, C:20만)으로 입력이 주어진다면 시간 제한을 통과하지 못하게 된다. (20만 팩토리얼..) 따라서 해당 방식으로 문제를 풀 수 없다.

     

    2) 이진탐색 방식

    문제를 살짝 다르게 생각하면 이진탐색방식으로 논리를 설계할 수 있다.

    문제에서 요구하는 답은 가장 인접한 두 공유기의 거리가 최대가 될 때의 '거리'이다. (두 공유기의 좌표가 아님) 따라서 '인접한 두 공유기 사이의 거리'를 탐색 기준으로 하여 이진 탐색을 해나가고, N개의 집 중 C개의 집에 공유기를 설치할 수 있는지 확인하면 된다.

     

    논리는 다음과 같다.

    - 탐색의 대상을 N개의 집에서 C개를 골랏을 때, '가장 인접한 집의 최소거리;로 설정한다.

    - 해당 최소거리로부터 주어진 좌표에서 설치할 수 있는 공유기의 개수를 센다.

    - 만약 설치가능개수가 C개 이상이라면 해당거리를 현재까지 구해진 최소거리의 최댓값과 비교한다.

    이진탐색으로 풀이하면 탐색범위가 절반씩 줄어들기 때문에 시간제한 안에 문제를 풀이할 수 있다.

     

    *이진탐색문제는 탐색대상을 설정하는 것이 제일 어려운것 같다...

    *탐색대상을 최소거리로 놓고 공유기 설치가능 개수를 구하는 것을 구현하는 것도 꽤 어려웠다.

     

     

     

    풀이

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.Arrays;
    import java.util.StringTokenizer;
    
    public class Main {
        static int N, C;
        static int[] houses;
    
        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()); // 2 이상
            C = Integer.parseInt(st.nextToken()); // 2 이상
            houses = new int[N];
    
            for (int i = 0; i < N; i++) {
                houses[i] = Integer.parseInt(br.readLine());
            }
            Arrays.sort(houses);
    
            // 최소 거리, 최대 거리
            int shortest = 1, longest = houses[N - 1] - houses[0];
            int result = 0;
            while (shortest <= longest) {
                int mid = (shortest + longest) / 2;
    
                if (isPossible(mid)) { // 공유기 C개 이상 설치 가능
                    result = Math.max(result, mid);
                    shortest = mid + 1;
                } else { // 공유기 C개 설치 불가
                    longest = mid - 1;
                }
            }// while
    
            System.out.println(result);
        }// main
    
    
        static boolean isPossible(int distance) {
            int wire_cnt = 0;
            int current = 0;
    
            for (int i = 0; i < N; i++) {
                if (current <= houses[i]){
                    wire_cnt++;
                    current = houses[i] + distance;
                }
            }
    
            return wire_cnt >= C;
        }
    }
    

     

     

     

    채점결과

     

     

     

    댓글

Designed by black7375.