https://www.acmicpc.net/problem/2512
2512번: 예산
첫째 줄에는 지방의 수를 의미하는 정수 N이 주어진다. N은 3 이상 10,000 이하이다. 다음 줄에는 각 지방의 예산요청을 표현하는 N개의 정수가 빈칸을 사이에 두고 주어진다. 이 값들은 모두 1 이상 100,000 이하이다. 그 다음 줄에는 총 예산을 나타내는 정수 M이 주어진다. M은 N 이상 1,000,000,000 이하이다.
www.acmicpc.net
이진탐색으로 푼 문제다. 이진탐색으로 풀어야 하니까 오름차순을 적용하였다. 예산을 찾을 때 가장 작은 예산을 찾는 범위의 시작으로 놓으면 틀린다. 왜냐하면 예산 총액이 처음에 불렀던 예산보다 작을 수 있기 때문이다. 이점을 지키고 예산을 찾았다면 답을 현재 찾은 예산으로 갱신하고 시작값을 현재 찾은 예산 + 1로 갱신한다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
int main() {
int n; //지방 자치단체 수
int num; //예산
int limit; //예산 총액
int res = 0; //처음에 불렀던 예산을 모두 더한 결과
int x; //답으로 채택할 최대 예산
vector<int> v; //예산들의 정보
cin >> n;
for (int i = 0; i < n; i++) {
cin >> num;
v.push_back(num);
res = res + num;
}
sort(v.begin(), v.end()); //오름차순 정렬
cin >> limit;
x = v[v.size() - 1];
if (limit >= res) {
cout << x;
}
else {
int left = 0; //제일 처음 주어진 예산보다 총액이 작은 예산이 들어올 수 있음으로 v[0]라 하면 틀림
int right = v[v.size() - 1]; //최대 예산
//이진 탐색을 통하여 최대가 될 수 있는 예산을 찾는다.
while (left <= right) {
int ans = 0;
int mid = (left + right) / 2;
for (int i = v.size() - 1; i >= 0; i--) {
int temp = v[i];
if (temp > mid) { //처음에 불렀던 예산이 현재 찾은 예산보다 큰 경우
temp = mid; //현재 찾은 예산으로 초기화
}
ans = ans + temp;
}
if (ans <= limit) {
x = mid;
left = mid + 1;
}
else {
right = mid - 1;
}
}
cout << x;
}
}
'백준' 카테고리의 다른 글
백준9935 - 문자열 폭발 (0) | 2019.12.23 |
---|---|
백준2805 - 나무 자르기 (0) | 2019.12.07 |
백준1987 - 알파벳 (0) | 2019.12.04 |
백준2596 - 비밀편지 (0) | 2019.12.02 |
백준17265 - 나의 인생에는 수학과 함께 (0) | 2019.12.01 |