알고리즘/백준 문제풀이

백준 [자바 java] 공유기 설치

잔디🌿 2023. 9. 14. 04:23

https://www.acmicpc.net/problem/2110

 

2110번: 공유기 설치

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

www.acmicpc.net

오랜만에 백준이다! 코드트리를 통해서 개념을 어느정도 익혔으니 실전에 적용해보는 연습을 슬슬 해보려고 한다.

 

이 문제는 내가 5개월 전에 시도했다가 못풀었던 문제이다.

집의 위치와 공유기의 수가 주어지고, 이를 적절하게 배치해서 공유기가 설치된 집 사이의 가장 가까운 거리가 최대가 되도록 해야한다.

 

 이 문제는 이진탐색으로 풀었고, lowerBound 개념이 들어간다. 이진 탐색을 통해서 가장 가까운 거리의 최댓값을 탐색했다. mid값이 가장 가까운 거리의 최대라고 했을 때 공유기를 배치해보고 공유기의 수가 주어진 c보다 크거나 같다면 유효한 값이라는 의미이므로, ans값을 갱신한다. 

 

공유기를 배치할 때에는 무조건 첫번째 집에는 설치된다고 가정하였다. 만약 첫번째 집에 설치하지 않는다면 전체 거리가 두번째 집 ~ 마지막집이 되므로 비효율적이기 때문이다.

 

내가 이 문제를 풀면서 두 가지 실수를 했다.

  1. 이진탐색을 할 때 while값에 (left < right)를 하는 바람에 left == right인 경우가 고려되지 않았다. 나는 left와 right모두 mid + 1, mid-1을 하기 때문에 꼭 < 대신 <= 를 사용해야 한다.
  2. right의 값을 n으로 지정했었다. mid는 공유기가 설치된 집 사이를 의미하므로 고려해봐야할 거리의 최댓값인 arr[n-1]을 넣었어야 했다.
import java.awt.*;
import java.io.*;
import java.util.*;
import java.math.*;

public class Main {
    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());

        int[] arr = new int[n];

        for(int i = 0;i<n;i++){
            arr[i] = Integer.parseInt(br.readLine());
        }

        Arrays.sort(arr);

        int left = 0;
        int right = arr[n-1];
        int mid = 0;

        int ans = 0;

        while(right >= left){
            mid = (left + right)/2;

            int now = 0;
            int cnt = 1;

            for(int i = 1;i<n;i++){
                if(arr[i] - arr[now] >= mid){
                    now = i;
                    cnt++;
                }
            }

            if(cnt < c) right = mid -1;
            else{
                left = mid +1;
                ans = Math.max(mid, ans);
            }
            //System.out.printf("%d %d\n",left,right);
        }

        System.out.println(ans);

    }
}