[백준] 2110번: 공유기 설치

조소복·2022년 12월 14일
0

문제

도현이의 집 N개가 수직선 위에 있다. 각각의 집의 좌표는 x1, ..., xN이고, 집 여러개가 같은 좌표를 가지는 일은 없다.

도현이는 언제 어디서나 와이파이를 즐기기 위해서 집에 공유기 C개를 설치하려고 한다. 최대한 많은 곳에서 와이파이를 사용하려고 하기 때문에, 한 집에는 공유기를 하나만 설치할 수 있고, 가장 인접한 두 공유기 사이의 거리를 가능한 크게 하여 설치하려고 한다.

C개의 공유기를 N개의 집에 적당히 설치해서, 가장 인접한 두 공유기 사이의 거리를 최대로 하는 프로그램을 작성하시오.

입력

첫째 줄에 집의 개수 N (2 ≤ N ≤ 200,000)과 공유기의 개수 C (2 ≤ C ≤ N)이 하나 이상의 빈 칸을 사이에 두고 주어진다. 둘째 줄부터 N개의 줄에는 집의 좌표를 나타내는 xi (0 ≤ xi ≤ 1,000,000,000)가 한 줄에 하나씩 주어진다.

출력

첫째 줄에 가장 인접한 두 공유기 사이의 최대 거리를 출력한다.

예제 입력 1

5 3
1
2
8
4
9

예제 출력 1

3

힌트

공유기를 1, 4, 8 또는 1, 4, 9에 설치하면 가장 인접한 두 공유기 사이의 거리는 3이고, 이 거리보다 크게 공유기를 3개 설치할 수 없다.

문제 풀이

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class BJ2110 {
    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 C=Integer.parseInt(st.nextToken());

        long[] home=new long[N];
        long max=0;

        for(int i=0;i<N;i++){
            home[i]=Long.parseLong(br.readLine());
            max=Math.max(max,home[i]);
        }

        Arrays.sort(home);

        long left=0;
        long right=max;
        long mid=0;

        while(left<=right){
            // 공유기 설치 거리
            mid=(left+right)/2;

            long cnt=1;
            int idx=0;
            for(int i=0;i<N;i++){
                if(home[idx]+mid<=home[i]){
                    cnt++;
                    idx=i;
                }
            }

            if(cnt>=C){
                left=mid+1;
            }
            else{
                right=mid-1;
            }

        }

        System.out.println(right);
    }
}

C개의 공유기를 집에 설치하는 데 이때, 가장 인접한 공유기의 최대 거리를 구하는 문제이다.

이 문제에서 고려해야할 점은 다음과 같다.

고려할 점

  • 공유기는 집에 설치되어야한다.
  • 가장 인접한 거리를 구했을 때, 다른 공유기의 거리는 해당 거리보다 멀어야한다.

이것을 고려하면서 이분탐색을 진행하면 된다.

이분탐색

long left=0;
long right=max;
long mid=0;

while(left<=right){
    // 공유기 설치 거리
    mid=(left+right)/2;

    long cnt=1;
    int idx=0;
    for(int i=0;i<N;i++){
        if(home[idx]+mid<=home[i]){
            cnt++;
            idx=i;
        }
    }

    if(cnt>=C){
        left=mid+1;
    }
    else{
        right=mid-1;
    }

}

System.out.println(right);

집의 위치를 입력받고 이분탐색을 진행하기 위해 배열을 정렬한 뒤 이분탐색을 수행한다.

탐색하고자 하는 값을 두 공유기의 가장 인접한 거리 로 둔다.

공유기를 두 개 설치한다고 했을 때 나올 수 있는 최대 거리는 마지막 위치에 있는 집까지의 거리이기 때문에 right는 마지막 집의 위치값으로 초기화한다.

이후 이분탐색을 진행하면서 무조건 첫 위치의 집에 공유기를 설치한다고 생각하고 mid 거리보다 멀리 떨어진 곳에 집이 있다면 그 곳에 공유기를 설치한다.

모든 공유기를 설치했을 때 설치해야하는 공유기의 수 C보다 크거나 같다면 거리를 더 넓힐 수 있기 때문에 left의 범위를 mid+1로 키운다.

반대로 C보다 작다면 거리를 좁혀 더 많은 공유기를 설치해야하므로 right의 범위를 mid-1로 줄인다.

이 과정을 모두 거치고 나면 구하고자 하는 공유기의 거리를 구할 수 있다.

profile
개발을 꾸준히 해보자

0개의 댓글