[백준 1654] 랜선 자르기(Java)

최민길(Gale)·2023년 2월 9일
1

알고리즘

목록 보기
36/172

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

이 문제는 이진 탐색으로 풀 수 있습니다. K가 10,000 이하, N이 1,000,000 이하이기 때문에 이중 반복문을 돌리게 될 경우 O(10^10) 으로 시간 초과가 나타납니다. 따라서 이진 탐색을 통하여 탐색 속도를 줄여야 합니다. 이진 탐색의 최댓값은 가장 큰 수로, 최솟값은 1로 설정하셔서 조건에 맞게 진행하시면 됩니다. 여기서 실수로 최솟값을 0으로 설정하시게 되면 mid가 0이 되어 0으로 나누는 런타임 에러가 발생할 수 있으니 조심하시면 됩니다.

다음은 코드입니다.

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

public class Main{
    static int K,N;
    static long max = 0, min = 1;
    // 랜선 길이가 int 범위를 초과하므로 long으로 받기
    static ArrayList<Long> req = new ArrayList<>();

    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());

        // 이진 탐색 실행
        // max : 가장 큰 수
        // min : 1

        for(int i=0;i<K;i++){
            st = new StringTokenizer(br.readLine());
            long num = Long.parseLong(st.nextToken());
            req.add(num);
            if(max < num) max = num;
        }

        while(min <= max){
            long mid = (min+max)/2;

            long sum = 0;
            for(int i=0;i<req.size();i++){
                // 랜선을 자른 길이만큼을 더함
                sum += (req.get(i)/mid);
            }

            // 만약 자른 길이의 합이 목표값보다 작다면
            // 현재 길이가 긴 것이므로 max값을 mid-1로 줄이기
            if(sum < N) max = mid-1;
            // 만약 자른 길이의 합이 목표값보다 크다면
            // 현재 길이가 짧은 것이므로 min값을 mid+1로 늘리기
            else min = mid+1;
        }

        // mid값이 mid+1인데 구하고자 하는 길이는 mid이므로 -1해서 진행하기
        System.out.println(min-1);
    }
}

profile
저는 상황에 맞는 최적의 솔루션을 깊고 정확한 개념의 이해를 통한 다양한 방식으로 해결해오면서 지난 3년 동안 신규 서비스를 20만 회원 서비스로 성장시킨 Software Developer 최민길입니다.

0개의 댓글