2023. 5. 17. 11:23ㆍC++/알고리즘
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
도대체 어느 부분에서 이분 탐색을 해야하는건가 했는데
'간격'의 탐색에서 이분 탐색을 활용하여 점점 좁혀나가는 문제였다.
공유기를 설치할때 앞에서부터 탐색하여 목표하는 간격값을 넘어가면 바로 공유기를 설치한다
→ 그리디
설치한 공유기 갯수와 목표 공유기 갯수를 비교하여 이분탐색으로 목표 간격값을 최대한 늘려나간다
→ 이분 탐색
1. 중간 간격값을 설정한다((최소 간격 + 최대 간격) / 2)
※ 처음 최소 간격은 1, 최대 간격은 (처음 집 - 끝의 집)
2. 해당 간격으로 처음 집부터 공유기를 설치하여서 공유기를 몇 개 설치할 수 있는지 확인해 본다.
※ 최소 간격이 최대가 되기 위해선 어차피 처음 집에는 무조건 공유기가 설치되어야 함에 유의
3. 설치된 공유기와 목표 공유기에 따라서
3-1. 설치된 공유기가 목표치보다 적다면 간격을 좁힌다.(최대 간격 = 중간 간격 - 1)
3-2. 설치된 공유기가 목표치보다 많다거나 같다면 간격을 넓힌다.(최소 간격 = 중간 간격 + 1)
4. 최소 간격이 최대 간격을 넘어갈때까지 1~3항을 반복한다.
→조건(설치 수)을 만족하는 최대 간격을 이분 탐색
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int N, C;
vector<int> Home;
int Solve(int mid)
{
int ret = 1;
int pre = Home[0];
for (int i = 1; i < Home.size(); i++)
{
if (Home[i] - pre >= mid)
{
ret++;
pre = Home[i];
}
}
return ret;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> N >> C;
int cmd = N;
while (cmd--)
{
int tmp;
cin >> tmp;
Home.push_back(tmp);
}
sort(Home.begin(), Home.end());
int ret = 0;
int s = 1;
int e = Home.back() - Home.front();
while (s <= e)
{
int mid = ((s + e) / 2);
if (Solve(mid) < C) e = mid - 1;
else
{
ret = max(ret, mid);
s = mid + 1;
}
}
cout << ret;
}
'C++ > 알고리즘' 카테고리의 다른 글
Quick Sort (0) | 2023.05.22 |
---|---|
레이스(이분 탐색, 그리디) (0) | 2023.05.17 |
계단 수(DP) (0) | 2023.05.15 |
여행(DP) (0) | 2023.05.11 |
벽장문의 이동(DP) (0) | 2023.05.10 |