λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
μ•Œκ³ λ¦¬μ¦˜

[Java] BOJ 1654 λžœμ„  자λ₯΄κΈ°

by 🍊귀🍊 2024. 7. 22.

문제 

문제 링크 https://www.acmicpc.net/problem/1654

  • μ˜€μ˜μ‹μ€ 자체적으둜 K개의 λžœμ„ μ„ 가지고 μžˆλ‹€.
  • κ·ΈλŸ¬λ‚˜ K개의 λžœμ„ μ€ 길이가 μ œκ°κ°μ΄λ‹€. 박성원은 λžœμ„ μ„ λͺ¨λ‘ N개의 같은 길이의 λžœμ„ μœΌλ‘œ λ§Œλ“€κ³  μ‹Άμ—ˆκΈ° λ•Œλ¬Έμ— K개의 λžœμ„ μ„ μž˜λΌμ„œ λ§Œλ“€μ–΄μ•Ό ν•œλ‹€.
  • 예λ₯Ό λ“€μ–΄ 300cm 짜리 λžœμ„ μ—μ„œ 140cm 짜리 λžœμ„ μ„ 두 개 μž˜λΌλ‚΄λ©΄ 20cmλŠ” 버렀야 ν•œλ‹€. (이미 자λ₯Έ λžœμ„ μ€ 뢙일 수 μ—†λ‹€.)
  • 편의λ₯Ό μœ„ν•΄ λžœμ„ μ„ 자λ₯΄κ±°λ‚˜ λ§Œλ“€ λ•Œ μ†μ‹€λ˜λŠ” κΈΈμ΄λŠ” μ—†λ‹€κ³  κ°€μ •ν•˜λ©°, 기쑴의 K개의 λžœμ„ μœΌλ‘œ N개의 λžœμ„ μ„ λ§Œλ“€ 수 μ—†λŠ” κ²½μš°λŠ” μ—†λ‹€κ³  κ°€μ •ν•˜μž.
  • 그리고 자λ₯Ό λ•ŒλŠ” 항상 μ„Όν‹°λ―Έν„° λ‹¨μœ„λ‘œ μ •μˆ˜κΈΈμ΄λ§ŒνΌ 자λ₯Έλ‹€κ³  κ°€μ •ν•˜μž. Nκ°œλ³΄λ‹€ 많이 λ§Œλ“œλŠ” 것도 N개λ₯Ό λ§Œλ“œλŠ” 것에 ν¬ν•¨λœλ‹€.
  • μ΄λ•Œ λ§Œλ“€ 수 μžˆλŠ” μ΅œλŒ€ λžœμ„ μ˜ 길이λ₯Ό κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.
  • 첫째 μ€„μ—λŠ” μ˜€μ˜μ‹μ΄ 이미 가지고 μžˆλŠ” λžœμ„ μ˜ 개수 K, 그리고 ν•„μš”ν•œ λžœμ„ μ˜ 개수 N이 μž…λ ₯λœλ‹€.
  • KλŠ” 1이상 10,000μ΄ν•˜μ˜ μ •μˆ˜μ΄κ³ , N은 1이상 1,000,000μ΄ν•˜μ˜ μ •μˆ˜μ΄λ‹€.
  • 그리고 항상 K ≦ N 이닀. κ·Έ ν›„ K쀄에 걸쳐 이미 가지고 μžˆλŠ” 각 λžœμ„ μ˜ 길이가 μ„Όν‹°λ―Έν„° λ‹¨μœ„μ˜ μ •μˆ˜λ‘œ μž…λ ₯λœλ‹€. λžœμ„ μ˜ κΈΈμ΄λŠ” 2^31-1보닀 μž‘κ±°λ‚˜ 같은 μžμ—°μˆ˜μ΄λ‹€.
  • 첫째 쀄에 N개λ₯Ό λ§Œλ“€ 수 μžˆλŠ” λžœμ„ μ˜ μ΅œλŒ€ 길이λ₯Ό μ„Όν‹°λ―Έν„° λ‹¨μœ„μ˜ μ •μˆ˜λ‘œ 좜λ ₯ν•œλ‹€.

아이디어

  • 이뢄탐색을 ν™œμš©ν•΄μ„œ ν’€μ—ˆλ‹€.
  • λžœμ„  길이λ₯Ό μž…λ ₯λ°›μœΌλ©΄μ„œ 찾은 μ΅œλŒ“κ°’μ„ 가지고 이뢄탐색을 ν–ˆλŠ”λ° μ‹œμž‘μ μ€ 1, 끝점은 μ΅œλŒ“κ°’μœΌλ‘œ 이뢄탐색을 ν–ˆλ‹€.
  • μ‹œμž‘μ κ³Ό 끝점을 λ”ν•΄μ„œ 2λ₯Ό λ‚˜λˆˆ κ°’μœΌλ‘œ λžœμ„ λ“€μ„ λ‚˜λˆ΄μ„ λ•Œ, λ‚˜μ˜¨ λͺ«λ“€μ„ λ”ν•œ 값이 ν•„μš”ν•œ λžœμ„  κ°œμˆ˜λ³΄λ‹€ μž‘λ‹€λ©΄ λžœμ„ κΈΈμ΄κ°€ 더  μ§§μ•„μ•Όλ˜λ―€λ‘œ μ‹œμž‘μ μ„ 1둜 끝점을 (μ‹œμž‘μ  + 끝점) / 2 - 1둜 작고 λ‹€μ‹œ 이뢄탐색을 λŒλ Έλ‹€.
  • λ§Œμ•½ ν•„μš”ν•œ λžœμ„  κ°œμˆ˜λ³΄λ‹€ κ°™κ±°λ‚˜ 크닀면 λžœμ„  길이λ₯Ό (μ‹œμž‘μ  + 끝점) / 2 둜 κ°±μ‹ ν•΄μ€€λ‹€.
  • 그리고 λžœμ„  길이가 더 κΈΈμ–΄λ„λ˜λ―€λ‘œ μ‹œμž‘μ μ„ (μ‹œμž‘μ  + 끝점) / 2 + 1둜 작고 끝점을 μ΅œλŒ“κ°’μœΌλ‘œ 작고 λ‹€μ‹œ 이뢄탐색을 λŒλ Έλ‹€.
  • 계속 이뢄탐색을 λŒλ¦¬λ‹€κ°€ 끝점이 μ‹œμž‘μ λ³΄λ‹€ κΈΈμ–΄μ§ˆ 경우, ν•¨μˆ˜λ₯Ό μ’…λ£Œν–ˆλ‹€. 

κ²ͺ은 μ‹œν–‰μ°©μ˜€

  • λ§Žμ΄λ„ ν‹€λ Έλ‹€... μ²˜μŒμ—λŠ” 정말 μ‰½κ²Œ μƒκ°ν•˜κ³  μ΅œμ†Ÿκ°’μ„ μ°Ύμ•„μ„œ κ±°κΈ°μ„œ 1μ”© λΉΌλ©΄μ„œ κ·Έ κ°’μœΌλ‘œ λžœμ„ λ“€μ„ λ‚˜λˆˆ λͺ«λ“€μ„ λ”ν–ˆμ„ λ•Œ ν•„μš”ν•œ λžœμ„  κ°œμˆ˜λ³΄λ‹€ κ°™κ±°λ‚˜ 크닀면 λ°˜λ³΅λ¬Έμ„ λ©ˆμΆ”λŠ” λ°©μ‹μœΌλ‘œ ν’€μ—ˆλ‹€. 
  • 그런데 λ‚΄κ°€ ν•˜λ‚˜ κ°„κ³Όν•œ 사싀이 μžˆμ—ˆλ‹€... λͺ¨λ“  λžœμ„ μ„ μ“Έ ν•„μš”κ°€ μ—†λ‹€λŠ” λœ»μ΄μ˜€λ‹€... 
  • κ·Έ ν›„λ‘œ μ΅œμ†Ÿκ°’μ„ μ΅œλŒ“κ°’μœΌλ‘œ λ°”κΎΈκ³  ν’€μ—ˆμ§€λ§Œ μ‹œκ°„μ΄ˆκ³Όκ°€ λ‚˜μ™”κ³  이뢄 νƒμƒ‰μœΌλ‘œ ν’€κ²Œ λ˜μ—ˆλ‹€.
  • κ·Έ 뒀에도 많이...도.. ν‹€λ ΈλŠ”λ°... 이뢄탐색 방법이 μ™„μ „ν•˜μ§€ μ•Šμ•„ λ§Žμ€ μ‹œν–‰μ°©μ˜€λ₯Ό κ²ͺ은 과정이닀... γ…Žγ…Ž 
  • κ·Έ 외에도 탐색 λ²”μœ„λ₯Ό μ˜λ―Έν•˜λŠ” λ³€μˆ˜λ“€μ€ longνƒ€μž…μ„ μ¨μ€˜μ•Όν–ˆμ—ˆλŠ”λ° intλ₯Ό μΌμ—ˆλ‹€... γ…œγ…œ (1 + (2^31-1) μ—μ„œ μ˜€λ²„ν”Œλ‘œκ°€ λ°œμƒν•˜κΈ° λ•Œλ¬Έμ΄λ‹€...)
  • κ·Έλž˜λ„ μˆ˜λ§Žμ€ μ‹œν–‰μ°©μ˜€λ“€ 후에 문제λ₯Ό ν‘Έλ‹ˆκΉŒ λΏŒλ“―ν–ˆλ‹€...!

γ…Žγ…Žγ…Ž... 였늘 λ¬Έμ œλ“€... νž˜λ“€λ‹€...
νž˜λ“  μ‹Έμ›€μ΄μ˜€λ‹€.... κ·Έλž˜λ„ 덕뢄에 이뢄탐색 방법은 ν™•μ‹€νžˆ μ•Œκ²Œλœ 것 κ°™λ‹€...γ…Žγ…Ž

μ½”λ“œ

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

public class BOJ1654 {
    static long max;
    static long result;
    static int K;
    static int N;
    static int lans[];

    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(br.readLine());

        // 가지고 μžˆλŠ” λžœμ„  개수
        K = Integer.parseInt(st.nextToken());
        // ν•„μš”ν•œ λžœμ„  개수
        N = Integer.parseInt(st.nextToken());

        // λžœμ„  μ €μž₯ λ°°μ—΄
        lans = new int[K];

        // μ΅œλŒ“κ°’μ„ μ €μž₯ν•  λ³€μˆ˜
        max = Integer.MIN_VALUE;

        for(int i = 0; i < K; i++){
            int l = Integer.parseInt(br.readLine());

            // 배열에 μ €μž₯
            lans[i] = l;

            // μ΅œλŒ“κ°’μ΄ μž…λ ₯받은 μˆ˜λ³΄λ‹€ 크닀면
            // μž…λ ₯받은 수λ₯Ό μ΅œμ†Ÿκ°’μœΌλ‘œ κ°±μ‹ 
            if(l > max){
                max = l;
            }
        }

        // 결과값을 μ €μž₯ν•  λ³€μˆ˜
        result = 0;

        cutting(1, max);

        System.out.println(result);
    }

    // λžœμ„  자λ₯΄λŠ” ν•¨μˆ˜
    public static void cutting(long s, long l){
        // μ‹œμž‘μ μ΄ 끝점보닀 더 컀진닀면 μ’…λ£Œ
        if(l - s < 0){
            return;
        }

        // λžœμ„ μ˜ 길이λ₯Ό (μ‹œμž‘μ  + 끝점)/2λ₯Ό ν•΄μ€Œ
        long len = (s + l) / 2;

        // 자λ₯Έ λžœμ„ μ˜ 개수
        long cnt = 0;

        // λ°˜λ³΅λ¬Έμ„ 톡해 λžœμ„ λ“€μ„ μž˜λΌμ„œ λͺ‡κ°œ λ‚˜μ˜€λŠ”μ§€ 더함
        for(int j = 0; j < K; j++){
            cnt = cnt + (lans[j] / len);
        }

        // λ§Œμ•½ 자λ₯Έ λžœμ„ λ“€μ˜ κ°œμˆ˜κ°€ ν•„μš”ν•œ λžœμ„  κ°œμˆ˜λ³΄λ‹€ ν¬κ±°λ‚˜ κ°™λ‹€λ©΄
        if(cnt >= N){
            // 쀑간값과 끝점을 κΈ°μ€€μœΌλ‘œ λ‹€μ‹œ ν•¨μˆ˜λ₯Ό 돌림
            result = len;
            cutting(len + 1, l);
        }
        // λ§Œμ•½ κ°œμˆ˜κ°€ μž‘λ‹€λ©΄ λžœμ„ μ˜ 길이가 더 μž‘μ•„μ•Όλœλ‹€λŠ” λœ»μ΄λ―€λ‘œ
        else{
            // μ‹œμž‘μ κ³Ό 쀑간점을 κΈ°μ€€μœΌλ‘œ λ‹€μ‹œ ν•¨μˆ˜λ₯Ό 돌림
            cutting(s, len - 1);
        }
    }
}



'μ•Œκ³ λ¦¬μ¦˜' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[Java] BOJ 1764 λ“£λ³΄μž‘  (2) 2024.07.23
[Java] BOJ 1874 μŠ€νƒ μˆ˜μ—΄  (14) 2024.07.23
[Java] BOJ 2108 톡계학  (2) 2024.07.22
[Java] BOJ 1966 ν”„λ¦°ν„° 큐  (0) 2024.07.21
[Java] BOJ 1929 μ†Œμˆ˜ κ΅¬ν•˜κΈ°  (0) 2024.07.21