https://www.acmicpc.net/problem/2512
문제
국가의 역할 중 하나는 여러 지방의 예산요청을 심사하여 국가의 예산을 분배하는 것이다. 국가예산의 총액은 미리 정해져 있어서 모든 예산요청을 배정해 주기는 어려울 수도 있다. 그래서 정해진 총액 이하에서 가능한 한 최대의 총 예산을 다음과 같은 방법으로 배정한다.
- 모든 요청이 배정될 수 있는 경우에는 요청한 금액을 그대로 배정한다.
- 모든 요청이 배정될 수 없는 경우에는 특정한 정수 상한액을 계산하여 그 이상인 예산요청에는 모두 상한액을 배정한다. 상한액 이하의 예산요청에 대해서는 요청한 금액을 그대로 배정한다.
예를 들어, 전체 국가예산이 485이고 4개 지방의 예산요청이 각각 120, 110, 140, 150이라고 하자. 이 경우, 상한액을 127로 잡으면, 위의 요청들에 대해서 각각 120, 110, 127, 127을 배정하고 그 합이 484로 가능한 최대가 된다.
여러 지방의 예산요청과 국가예산의 총액이 주어졌을 때, 위의 조건을 모두 만족하도록 예산을 배정하는 프로그램을 작성하시오.
입력
첫째 줄에는 지방의 수를 의미하는 정수 N이 주어진다. N은 3 이상 10,000 이하이다. 다음 줄에는 각 지방의 예산요청을 표현하는 N개의 정수가 빈칸을 사이에 두고 주어진다. 이 값들은 모두 1 이상 100,000 이하이다. 그 다음 줄에는 총 예산을 나타내는 정수 M이 주어진다. M은 N 이상 1,000,000,000 이하이다.
출력
첫째 줄에는 배정된 예산들 중 최댓값인 정수를 출력한다.
예제 입력 1
4
120 110 140 150
485
예제 출력 1
127
풀이
이분 탐색을 적용하기 위해서는 우선 오름차순 정렬부터 해주어야 한다.
그리고 이분 탐색을 하면서 예산의 상한액을 계산해 나간다.
만약 중간 이후에 상한액보다 작은 경우가 존재 한다면, 상한액을 더 올려도 되기 때문에 low = mid+1로 바꿔준다.
만약 중간 이전에 상한액보다 큰 경우가 존재 한다면, 상한액을 낮춰야 하기 때문에 high = mid -1로 바꿔준다.
그 외의 경우엔 답을 찾은 것이므로 그를 출력해 준다.
혹시 몰라서 int를 사용하지 않고 long long형을 사용하였다.
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
long long money[10001];
void sol(int n, long long m){
int low = 0;
int high = n;
int mid;
long long be_mid=0;
long long max_money;
while(high >= low){
be_mid = 0;
mid = (high+low)/2;
for(int i=0; i<mid; i++){
be_mid+=money[i];
}
if (be_mid > m){
high = mid-1;
}
else{
max_money = m - be_mid;
if(mid == n){
printf("%lld\n", money[n-1]);
exit(0);
}
max_money = max_money / (n-mid);
if (money[mid-1] > max_money){
high = mid-1;
}
else if (money[mid] < max_money){
low = mid+1;
}
else{
printf("%lld\n", max_money);
exit(0);
}
}
}
}
int main (void) {
int n;
long long m;
scanf("%d", &n);
for(int i=0; i<n; i++){
scanf("%lld", &money[i]);
}
scanf("%lld", &m);
sort(money, money+n);
sol(n, m);
}
'알고리즘 > PS - 백준' 카테고리의 다른 글
[백준 2776 - C++] 암기왕 : 이분 탐색 (0) | 2021.05.20 |
---|---|
[백준 2805 - C++] 나무 자르기 : 이분 탐색 (0) | 2021.05.20 |
[백준 2263 - C++] 트리의 순회 : 분할 정복 (0) | 2021.05.15 |
[백준 10830 - C++] 행렬 제곱 : 분할 정복 (0) | 2021.05.14 |
[백준 1493 - C++] 박스 채우기 : 분할 정복 (0) | 2021.05.14 |