티스토리 뷰
Algorithm/[Java+Python+JavaScript]BackJoon
[Java+Python]2110번, 공유기 설치
Vagabund.Gni 2023. 6. 27. 12:01728x90
반응형
목차
이진 탐색
문제
도현이의 집 N개가 수직선 위에 있다. 각각의 집의 좌표는 $x_1, ..., x_N$이고, 집 여러 개가 같은 좌표를 가지는 일은 없다.
도현이는 언제 어디서나 와이파이를 즐기기 위해서 집에 공유기 C개를 설치하려고 한다.
최대한 많은 곳에서 와이파이를 사용하려고 하기 때문에, 한 집에는 공유기를 하나만 설치할 수 있고,
가장 인접한 두 공유기 사이의 거리를 가능한 크게 하여 설치하려고 한다.
C개의 공유기를 N개의 집에 적당히 설치해서, 가장 인접한 두 공유기 사이의 거리를 최대로 하는 프로그램을 작성하시오.
입력
첫째 줄에 집의 개수 N (2 ≤ N ≤ 200,000)과 공유기의 개수 C (2 ≤ C ≤ N)이 하나 이상의 빈칸을 사이에 두고 주어진다.
둘째 줄부터 N개의 줄에는 집의 좌표를 나타내는 $x_i (0 ≤ x_i ≤ 1,000,000,000)$가 한 줄에 하나씩 주어진다.
출력
첫째 줄에 가장 인접한 두 공유기 사이의 최대 거리를 출력한다.
풀이
계속되는 이진 탐색 문제이다. 이번엔 집의 좌표가 주어지고 설치해야 하는 공유기의 개수가 주어진다.
집의 좌표마다 공유기를 설치하되, 공유기 사이의 거리가 최대가 되도록 하고, 그 최대 거리를 출력하는 문제이다.
이전까지의 이진 탐색에 익숙해져 있다면 크게 어려울 것이 없다.
알고리즘은 다음과 같다.
- 집의 개수 n과 공유기의 개수 c를 입력받은 뒤, 각 집의 위치를 크기 n인 배열(리스트) houses에 저장한다.
- 이진 탐색을 수행하기 위해 houses를 오름차순으로 정렬한다.
- left = 1, right = houses[n - 1] - houses[0]으로, 답을 저장할 answer = 0으로 초기화한다.
- 이진 탐색을 시작한다. left <= right인 동안 아래의 과정을 반복한다.
- mid = (left + right) / 2로, 시작점 start = houses[0]으로, count = 1로 초기화한다.
- houses 배열을 순회하면서 각 집과 start 사이의 거리를 계산하고 해당 거리가 mid보다 크거나 같으면
count를 증가시키고 start를 현재 house의 위치로 갱신한다.
(이 과정은 공유기가 두 대 이상이기 때문에 전체 길이의 절반을 넘는 값은 버리는 역할을 한다.) - count >= c 라면 answer = mid, left = mid + 1로 갱신하고, 그 반대라면 right = mid - 1로 갱신한다.
- 탐색이 종료된 후 answer를 출력한다.
Java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Prob2110 {
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[] houses = new int[n];
for (int i = 0; i < n; i++) {
houses[i] = Integer.parseInt(br.readLine());
}
Arrays.sort(houses);
int left = 1;
int right = houses[n - 1] - houses[0];
int answer = 0;
while (left <= right) {
int mid = (left + right) / 2;
int start = houses[0];
int count = 1;
for (int house : houses) {
int distance = house - start;
if (distance >= mid) {
count++;
start = house;
}
}
if (count >= c) {
answer = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
System.out.println(answer);
}
}
Python
import sys
n, c = map(int, sys.stdin.readline().rstrip().split())
houses = [int(sys.stdin.readline().rstrip()) for _ in range(n)]
houses = sorted(houses)
left = 1
right = houses[n - 1] - houses[0]
answer = 0
while left <= right:
mid = (left + right) // 2
start = houses[0]
count = 1
for house in houses:
distance = house - start
if distance >= mid:
count += 1
start = house
if count >= c:
answer = mid
left = mid + 1
else:
right = mid - 1
print(answer)
Performance
반응형
'Algorithm > [Java+Python+JavaScript]BackJoon' 카테고리의 다른 글
[JavaScript]10810번, 공 넣기, 배열 선언 및 초기화, process.stdout.write() (0) | 2023.06.30 |
---|---|
[Java+Python]2805번, K번째 수 (0) | 2023.06.29 |
[JavaScript]2562, 최댓값, 그리고 최솟값, rl.on(), 배열 다루기 (1) | 2023.06.28 |
[JavaScript]2408번, 주사위 세 개 (0) | 2023.06.26 |
[JavaScript]14681번, 사분면 고르기 (0) | 2023.06.24 |
[Java+Python]2805번, 나무 자르기 (0) | 2023.06.23 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 유럽여행
- RX100M5
- Python
- Algorithm
- 스트림
- 면접 준비
- 세계일주
- 파이썬
- a6000
- 유럽
- 세계여행
- 스프링
- spring
- 세모
- 중남미
- 리스트
- 남미
- 기술면접
- 자바
- 칼이사
- 동적계획법
- 백준
- 알고리즘
- 야경
- 지지
- java
- BOJ
- Backjoon
- 여행
- 맛집
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함