택시짱의 개발 노트

[프로그래머스] 예산 본문

알고리즘

[프로그래머스] 예산

택시짱 2020. 1. 25. 13:30

링크

https://programmers.co.kr/learn/courses/30/lessons/43237

 

코딩테스트 연습 - 예산 | 프로그래머스

국가의 역할 중 하나는 여러 지방의 예산요청을 심사하여 국가의 예산을 분배하는 것입니다. 국가예산의 총액은 미리 정해져 있어서 모든 예산요청을 배정해 주기는 어려울 수도 있습니다. 그래서 정해진 총액 이하에서 가능한 한 최대의 총 예산을 다음과 같은 방법으로 배정합니다. 1. 모든 요청이 배정될 수 있는 경우에는 요청한 금액을 그대로 배정합니다. 2. 모든 요청이 배정될 수 없는 경우에는 특정한 정수 상한액을 계산하여 그 이상인 예산요청에는 모두 상한액을

programmers.co.kr

풀이

정해진 예산의 총액 이하에서 가능한 최대의 총 예산을 구해야 한다.

 

처음 생각을 했을때는 총 예산/n 보다 작은 지방 예산을 총 예산에서 점점 빼 가며 최대의 예산을 구하면 되지 않을까 라고 생각을 하였지만, 시간복잡도에서 o(n^2)이 나올수 있을거 같아 다른 생각을 하다 이분탐색을 이용 하게 되었다.

 

이분 탐색은 left, right, mid 를 이용하여 o(log n)의 시간복잡도를 가지는 알고리즘 이며

밑의 코드에서 left, right, mid는 배정 가능한 예산을 저장하는 변수 이다.

left에는 나올수 있는 예산중 가장 작은 수인 1

right에는 나올수 있는 예산중 가장 큰 수(budgets을 정렬한 맨 끝 수)인 budgets.end()

mid는 (left + right)/2의 값

 

지방에서 요청한 금액이 상한액 미만의 금액이면 지방에서 요청한 금액을 그대로 예산의 합계에 더해주고

반대로 지방에서 요청한 금액이 상한액 이상이라면 상한액을 더해주고

 

이때 더해준 예산의 총 합이 국가의 예산보다 높으면 right를 mid-1 로 갱신하여 상한 금액을 줄여주고

반대로 예산이 작으면 left를 mid+1로 갱신하여 상한 금액을 높여 준다.

 

left를 갱신해 줄때 상한액은 점점 증가하고 있기때문에 answer를 mid로 저장해주면 최대값이 계속 갱신 된다.

#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<string>
#include<set>
#include<map>
#include<cstring>

#define INF 1e9
#define SIZE 110000

using namespace std;

typedef long long int ll;

int solution(vector<int> budgets, int M) {
	sort(budgets.begin(), budgets.end());
	int left = 1 , right = budgets.back(), mid;
	int answer = 0;

	while (left <= right) {
		mid = (left + right) / 2;
		int sum = 0;
		for (auto b : budgets) {
			if (b <= mid) {
				sum += b;
			}
			else if (b > mid) {
				sum += mid;
			}
		}

		if (sum <= M) {
			left = mid + 1;
			answer = mid;
		}
		else {
			right = mid - 1;	
		}
	}

	return answer;
}

반응형

'알고리즘' 카테고리의 다른 글

[백준] 2206번 - 벽 부수고 이동하기  (0) 2020.02.01
[백준] 3190번 - 뱀  (0) 2020.01.30
[프로그래머스] 가장 먼 노드  (0) 2020.01.26
[프로그래머스] 섬 연결하기  (0) 2020.01.24
[백준] 2294번 동전 2  (0) 2020.01.24
Comments