본문 바로가기
알고리즘/백준

[백준 / 예산 / JAVA / 이진 탐색]

by KDW999 2023. 5. 6.

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

 

2512번: 예산

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

www.acmicpc.net

 

문제 접근

 

예산액을 배열로 만들고 값을 저장,

이 문제에선 배열을 정렬안하고도 풀 수 있던데 난 일단 정렬해서 풀었다.

 

총 요청 예산액이 총 예산보단 작다면 가장 큰 요청 예산액을 출력

 

아니라면 상한액을 탐색해 나간다.

상한액은 반씩 잘라가면서 탐색해가고 배열 값들과 현재 상한액을 비교하면서 작은 값은 그대로 합하고 큰 값은 상한액을 더한다.

 

더한 총 값이 총 예산보다 작으면 return시켜줄 값(result)을 mid로 저장해놓는다.

이 작업을 반복하면서 left가 right를 넘기직전 가장 최근에 저장된 result값이 상한액이 된다.  

 

++ 조건을 떠올리는게 중요

import java.util.*;
import java.io.*;

public class Main {
	static int N;
	static int[] province;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		N = Integer.parseInt(br.readLine()); // 지방 수
		province = new int[N];
		
		int sum = 0;
		StringTokenizer st = new StringTokenizer(br.readLine());
		for(int i=0; i<N; i++) {
			province[i] = Integer.parseInt(st.nextToken());
			sum += province[i];
		}
		Arrays.sort(province);
		
		int budget = Integer.parseInt(br.readLine());
		
		if(sum <= budget) System.out.println(province[province.length-1]);
		else {
			limitCost(0, province[province.length-1], budget);
		}
		
	}
	
	public static void limitCost(int left, int right, int budget) {
		
		int result = 0;
		
		while(left <= right) {
			int mid = (left + right) / 2;
			
			int sum = 0;
			
			for(int i=0; i<N; i++) {
				// 현재 상한액(mid)보다 큰 예산 요청액이면 현재 상한액을 저장
				if(province[i] > mid) sum += mid;
				// 현재 상한액 보다 작은 예산 요청액이면 줄 수 있는 금액이기에 바로 저장
				else if(province[i] <= mid) sum += province[i];
			}
			
			if(sum > budget) right = mid -1;
			else {
				result = mid;
				left = mid + 1;
			}
		}
		System.out.println(result);
	}
}

댓글