* 의사코드
- 행동영역
- f(x) 정의시 최대, 최소를 쓰지마라. 우리는 이문제를 결정문제로 바꿔서 풀어야한다.
- 간격을 고정하고 탐색하라. (x)로 고정.
- 되는지를 구현하는게 사실 핵심이다. (go 함수)
- 참인경우, st = mid 임에 주의 // en = mid 아님!
- go 함수 구현
- 완탐하면서 간격 <= 차이(cur, next) -> 설치(cur갱신) , cnt+1
- 설치된 공유기 갯수가 c 보다 큰지 return
//설치간격이 x 일때, 공유기 c개 이상 설치 가능한지
ll go(ll x) {
ll cur = arr[0]; //현재 설치된 위치
ll cnt = 1; //공유기 설치갯수, 1st는 항상설치
for (int i = 1; i < n; ++i) {
if (x <= abs(cur - arr[i])) { //이상이면 설치하면됨 (2 ,4) 에서 간격이 1인경우 4에 설치가능
cur = arr[i];
cnt++;
}
}
return cnt >= c;
}
- f(x) 정의, go 함수 구현 모두 빡센 문제였다.
- f(x)를 현재간격으로 "고정" 하고
- 간격이 x일때 설치되는 공유기 수를 세고
- 그 값이 c 개 이상인지 확인.
* 전체코드
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, c;
ll arr[200000+4];
ll ret; //배정된 예산중 최대값
//설치간격이 x 일때, 공유기 c개 이상 설치 가능한지
ll go(ll x) {
ll cur = arr[0]; //현재 설치된 위치
ll cnt = 1; //공유기 설치갯수, 1st는 항상설치
for (int i = 1; i < n; ++i) {
if (x <= abs(cur - arr[i])) { //이상이면 설치하면됨 (2 ,4) 에서 간격이 1인경우 4에 설치가능
cur = arr[i];
cnt++;
}
}
return cnt >= c;
}
int main()
{
cin >> n>>c;
for (int i = 0; i < n; ++i) {
cin >> arr[i];
}
sort(arr, arr + n);
ll st = 1; // 최소간격
ll en = arr[n - 1] - arr[0]; //최대간격
//f(x) : 설치간격이 x일때, 되는지
while (st < en) {
ll mid = (st + en+1) / 2;
//cout << st << " "<< mid<<" " << en << "\n";
if (go(mid)) {
st = mid;
}
else {
en = mid - 1;
}
}
cout << st;
return 0;
}
'Algorithm > 매개변수 탐색' 카테고리의 다른 글
[Algo] 백준 예산 c++ // 매개변수 탐색 (0) | 2024.09.09 |
---|---|
[Algo] 백준 랜선자르기 c++ // 매개변수 탐색 (0) | 2024.09.08 |
백준 2110 공유기설치 c++ // 매개변수탐색, 이분탐색 hard (0) | 2024.03.29 |
백준 2805 나무자르기 c++ // 이분탐색, 매개변수탐색, 정답후보를 for문 돌려라 (0) | 2024.03.10 |