부잣집 문제인듯
문제풀이
처음에 문제가 이해가 안 되었다. 하나의 공유기를 사용가능한 수평거리를 알려줘야 하는게 아닌가 생각했는데, 그게 필요없는 문제였다.
어쨋거나, N개의 집에 C개의 공유기를 설치하는데, 가장 인접한 두 공유기 사이의 거리를 최대로 해야 한다고 한다..
가장 인접한 공유기의 거리 d 를 하나 정하면, 모든 , 공유기 사이의 거리들은 d이상 이어야 한다.
라고 생각하니, 나무자르기 문제가 생각났다.(MAX, MIN이 있다고 생각하니..) 이것도 이분법 문제 같다.
n의 개수가 최대 20만개이기 때문에 O(n^2)만 되어도 40억이 되기에 시간초과의 위험이 생긴다. 이분탐색이 생각나는데 모르겠다
알고리즘
구현
💥주의
- 가장 마지막으로 조건을 모두 만족했을 때의 "거리"를 저장해 둬야 한다.
--> Find할 때 마다 변수 "success"에 "해당 거리"를 저장.
#include<iostream>
#include <algorithm>
#include <vector>
using namespace std;
vector<int> distance_v;
int dist_table[200001]; // store distance between houses .
int n, c;
int min_dist, max_dist; // min idx, max idx.
// target : Goal distance
/*
Return
-1 : d를 줄일 것
1 : d를 늘릴 것.
*/
int check(int target)
{
int cur = 0;
int temp_tot_distance = 0;
int cnt = 1; // the number of house installed. starting with first house.
while (cur < n-1 ) {
int distance = dist_table[cur]; // distance untill next home
temp_tot_distance += distance;
if (temp_tot_distance >= target) {
cnt++;
temp_tot_distance = 0;
}
cur++;
}
if (cnt >= c) return 1;
else return -1;
}
int my_bin_search()
{
int success=-1;
int left = min_dist, right = max_dist;
int mid;
while (left <= right) {
mid = (left + right) / 2;
if (check(mid)>0) {
left = mid + 1;
success = mid;
//cout << "Success : " << mid << endl;
}
else {
right = mid - 1;
}
}
return success; // left>right된 경우, success했던 case가 while문 안에 하나는 있을테니.
}
int main()
{
cin >> n >> c;
min_dist=1000000000, max_dist = 0;
// 각 집의 위치를 저장 벡터
for (int i = 0; i < n; i++) {
int temp;
cin >> temp;
distance_v.push_back(temp);
}
// 순서대로 정렬 --> 집의 거리 순 정렬
sort(distance_v.begin(), distance_v.end());
// 집 사이 거리 중 max값
max_dist = distance_v[n - 1] - distance_v[0];
// 모든 두 집 사이의 거리구하기.--> min찾아야.. -> min을 구하는데 O(n)
for (int i = 0; i < n - 1; i++) {
int dist = distance_v[i + 1] - distance_v[i];
dist_table[i] = dist;
if (min_dist > dist)min_dist = dist;
}
int result = my_bin_search();
cout << result;
}