[BOJ] 백준 2110 - 공유기 설치 풀이
1. 문제
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
2. 풀이
이분탐색을 활용한 골드V 문제이다. 문제를 풀면서 이분탐색의 Upper_bound, Lower_bound가 정확히 기억이 나지 않아 글을 찾아보면서 문제를 해결했다.
https://blog.naver.com/bestmaker0290/220820005454
알고리즘 기초 - Lower Bound & Upper Bound
Lower Bound와 Upper Bound는 일종의 이분 탐색에서 파생된 것으로, 이분 탐색이 '원하는 값 k를 ...
blog.naver.com
https://www.acmicpc.net/blog/view/109
이분 탐색(Binary Search) 헷갈리지 않게 구현하기
개요 이분 탐색은 off-by-one error가 발생하기 쉬워서 늘 헷갈립니다. 이분 탐색 문제를 풀다보면 탈출 조건으로 lo <= hi, lo < hi, lo + 1 < hi 중 어느 걸 선택해야 할 지, 정답이 lo인지 hi인지 (lo + hi) / 2
www.acmicpc.net
먼저 문제를 파악해보자!
집의 개수와 설치해야하는 공유기의 수, 그리고 집들의 좌표가 주어진다. 이 문제의 핵심은 인접한 공유기의 거리 중에서 최소값 중 최대값이다. 힌트에서도 나와 있듯이 1, 4, 8로 설치했을 때 인접한 공유기의 최소값은 3이 된다. 만약 1에 설치한 후 8, 9에 설치했다면 인접한 공유기의 거리중 최소 값은 1이 된다.
그렇다면 이분탐색을 어떻게 적용해야 할까?
문제에서 주어지는 것은 좌표이고 답으로 요구하는 것은 '거리'이다. 이 거리에 따라 설치할 수 있는 공유기의 개수가 달라진다.
결국 거리를 탐색의 범위로 설정하고 이분탐색을 진행하면서, 해당 거리에 대해 설치 가능한 공유기의 개수에 따라 탐색하는 거리의 범위를 좁혀나가는 방식으로 적용하면 된다.
3. 소스코드
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.*;
class Main {
static int[] line;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken()); // 집의 개수
int C = Integer.parseInt(st.nextToken()); // 공유기의 개수
line = new int[N];
for (int i = 0; i < N; i++) {
line[i] = Integer.parseInt(br.readLine());
}
Arrays.sort(line);
int mid = 0;
int start = 1;
int end = line[N - 1] - line[0] + 1;
while (start < end) {
mid = (start + end) / 2;
if (install(mid) < C) {
end = mid;
}
else {
start = mid + 1;
}
}
bw.write(Integer.toString(start - 1));
bw.flush();
bw.close();
br.close();
}
private static int install(int dist) {
int cnt = 1; // 첫 번째 집에는 무조건 설치
int endLocated = line[0];
for (int i = 1; i < line.length; i++) {
int lo = line[i];
if (lo - endLocated >= dist) {
cnt += 1;
endLocated = lo;
}
}
return cnt;
}
}