본문 바로가기
알고리즘 풀이/백준

[Gold IV] 공유기 설치 - 2110 (Java)

by cornsilk-tea 2023. 7. 5.

문제 요약

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

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

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


문제 분석

첫집에 무조건 공유기를 설치한다 가정하고, 공유기 거리를 이분탐색을 통해 지속적으로 갱신하며 설치 가능한 공유기 개수를 카운트한다.

 

N=6, C=4, map={0,3,4,7,9,10}일때

코드

package Week17;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class BOJ_2110 {
    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());
        C = Integer.parseInt(st.nextToken());
        houses = new int[N];
        for(int i = 0; i < N; i++){
            houses[i] = Integer.parseInt(br.readLine());
        }
        Arrays.sort(houses);
        // 이분탐색으로 적절한 거리값을 탐색한다.
        // 탐색할 거리 범위 지정
        // 최소범위값는 0
        int minDistance = 0;
        // 최대범위값는 가장 끝값 - 첫값
        int maxDistance = houses[N-1] - houses[0];
        int result = 0;
        while(minDistance <= maxDistance){
            int selectedDistance = (minDistance + maxDistance) / 2;
            // 가장 첫 위치는 무조건 공유기를 설치한다.
            int cnt = 1;
            // 거리 계산을 위해 이전집을 저장한다.
            int prevHouse = houses[0];
            // 현재 탐색중인 거리 mid를 기준으로, 설치할 수 있는 집을 탐색
            for(int i = 1; i < N; i++){
                if(houses[i] - prevHouse >= selectedDistance){
                    cnt++;
                    prevHouse = houses[i];
                }
            }
            /*
                C를 찾았더라도 계속 탐색하는 이유:
                처음 찾은 저 값이 꼭 최적의 해라는 보장이 없기 때문에,
                전체 탐색한 후 지속해서 최적값을 갱신해준다.
             */
            // 현재 설치 가능한 공유기 개수가 C개 이상이라면?
            if(cnt >= C){
                result = selectedDistance;
                minDistance = selectedDistance + 1;
            }
            // 현재 설치 가능한 공유기 개수가 C개 미만이라면?
            else {
                maxDistance = selectedDistance - 1;
            }
        }
        System.out.println(result);
    }
}

정리

새로 배운 내용

없음

개선할 점

이분탐색을 진행할 때, 어떤 값을 찾아야 하는지 찾는데 애를 먹었다.

더 찾아볼만한 사항

이 코드는 좀 더 최적화가 불가능할까?