jusung-c
으 하기싫어
jusung-c
  • 공부 기록 (96)
    • Spring (42)
      • Spring 기초 이론 (8)
      • Spring 핵심 원리 - 기본 (9)
      • Blog 만들기 with SpringBoot (25)
    • JAVA (7)
      • Java 문법 (2)
      • 객체지향의 사실과 오해 (5)
    • Algorithm (47)
      • 자료구조 (3)
      • 완전탐색 (22)
      • 정렬 (4)
      • 이분탐색 (12)
      • 투 포인터 (4)
hELLO · Designed By 정상우.
jusung-c

으 하기싫어

BOJ 2512 - 예산
Algorithm/이분탐색

BOJ 2512 - 예산

2022. 5. 2. 21:27

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

 

2512번: 예산

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

www.acmicpc.net

 

 

 

  • 지방의 수 N (3 <= N <= 1만)
  • 각 지방의 예산들은 모두 1 이상 10만 이하
  • 나라의 총 예산 M (N <= M <= 10억)

 

아이디어

정해진 총액 이하에서 가능한 한 최대의 총 예산을 구해야 하는 문제로 " 최대 " 라는 키워드가 나왔으니 먼저 이분 탐색을 고려해본다.

 

원래 문제

  • 나라의 총 예산 M을 최대한 사용할 수 있는 예산 상한선은 얼마인가?

 

이분탐색을 위해 상한선을 H라고 하고 문제를 뒤집어서 Yes or No 문제로 만든다.

 

뒤집어서 만든 Yes or No 문제

  • 상한선이 H일 경우 나라의 총 예산 M 안에서 배정이 가능한가?

 

이분탐색을 진행해서 상한선 H 마다 Yes or No를 채우고 마지막 Yes인 H를 찾아낸다.

H의 범위는 1~요청 예산의 최대값.

 

 

시간 복잡도

  • Yes or No 질문을 한번 할 때마다 걸리는 시간은 O(N)
  • 이분 탐색 진행시 탐색 범위가 1~10만 이므로 최대 질문 수는 log 10만이 돼서 O(log 10만)의 시간 복잡도를 가진다.
  • 총 O(N log 10만)의 시간 복잡도를 가져서 1초안에 풀이가 가능하다.

 

구현

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

public class Main {
    static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    static int N, M;
    static int[] plz;

    static void init() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        N = Integer.parseInt(br.readLine());
        plz = new int[N + 1];

        StringTokenizer st = new StringTokenizer(br.readLine(), " ");
        for (int i = 1; i <= N; i++) {
            plz[i] = Integer.parseInt(st.nextToken());
        }

        M = Integer.parseInt(br.readLine());
    }

    static void pro() throws IOException {
        // 이분탐색
        int L = 0;
        int R = 0;
        for (int i = 1; i <= N; i++) {
            R = Math.max(plz[i], R);
        }

        int ans = 0;

        while (L <= R) {
            int mid = (L + R) / 2;

            if (YesOrNo(mid) == true) {
                ans = mid;
                L = mid + 1;
            } else {
                R = mid - 1;
            }
        }

        bw.write(ans+" ");
    }

    static boolean YesOrNo(int H) {
        int sum = 0;

        for (int i = 1; i <= N; i++) {
            sum += Math.min(H, plz[i]);
        }

        if (sum <= M) {
            return true;
        } else {
            return false;
        }
    }

    public static void main(String[] args) throws IOException {
        init();

        pro();

        bw.close();
    }

}

 

 

 

저작자표시 비영리 변경금지 (새창열림)

'Algorithm > 이분탐색' 카테고리의 다른 글

BOJ 2343 - 기타 레슨  (0) 2022.05.09
BOJ 2110 - 공유기 설치  (0) 2022.05.08
BOJ 1654 - 랜선 자르기  (0) 2022.05.02
BOJ 2805 - 나무 자르기  (0) 2022.05.01
매개 변수 탐색 (Parametric Search)  (0) 2022.05.01
    'Algorithm/이분탐색' 카테고리의 다른 글
    • BOJ 2343 - 기타 레슨
    • BOJ 2110 - 공유기 설치
    • BOJ 1654 - 랜선 자르기
    • BOJ 2805 - 나무 자르기
    jusung-c
    jusung-c

    티스토리툴바