알고리즘/PS - 백준

[백준 2512 - C++] 예산 : 이분 탐색

excited-hyun 2021. 5. 19. 23:41
반응형

https://www.acmicpc.net/problem/2512

 

2512번: 예산

첫째 줄에는 지방의 수를 의미하는 정수 N이 주어진다. N은 3 이상 10,000 이하이다. 다음 줄에는 각 지방의 예산요청을 표현하는 N개의 정수가 빈칸을 사이에 두고 주어진다. 이 값들은 모두 1 이상

www.acmicpc.net

문제

국가의 역할 중 하나는 여러 지방의 예산요청을 심사하여 국가의 예산을 분배하는 것이다. 국가예산의 총액은 미리 정해져 있어서 모든 예산요청을 배정해 주기는 어려울 수도 있다. 그래서 정해진 총액 이하에서 가능한 한 최대의 총 예산을 다음과 같은 방법으로 배정한다.

  1. 모든 요청이 배정될 수 있는 경우에는 요청한 금액을 그대로 배정한다.
  2. 모든 요청이 배정될 수 없는 경우에는 특정한 정수 상한액을 계산하여 그 이상인 예산요청에는 모두 상한액을 배정한다. 상한액 이하의 예산요청에 대해서는 요청한 금액을 그대로 배정한다. 

예를 들어, 전체 국가예산이 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);
}
728x90
반응형