본문 바로가기

Java/백준

[JAVA] 백준 1654 랜선 자르기

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

 

1654번: 랜선 자르기

첫째 줄에는 오영식이 이미 가지고 있는 랜선의 개수 K, 그리고 필요한 랜선의 개수 N이 입력된다. K는 1이상 10,000이하의 정수이고, N은 1이상 1,000,000이하의 정수이다. 그리고 항상 K ≦ N 이다. 그

www.acmicpc.net

 

- 집에서 시간을 보내던 오영식은 부름을 받고 급히 달려왔다. 박성원이 캠프 때 쓸 N개의 랜선을 만들어야 하는데 너무 바빠서 영식이에게 도움을 청했다.

 

- 이미 오영식은 자체적으로 K개의 랜선을 가지고 있다. 그러나 K개의 랜선은 길이가 제각각이다. 박성원은 랜선을 모두 N개의 같은 길이의 랜선을 만들고 싶었기 때문에 K개의 랜선을 잘라서 만들어야 한다. 

 

- 예를들어 300cm 짜리 랜선에서 140cm짜리 랜선을 두개 잘라내면 20cm는 버려야 한다. .

(이미 자른 랜선은 붙일 수 없다.)

 

- 편의를 위해 랜선을 자르거나 만들 때 손실되는 길이는 없다고 가정하며, 기존의 K개의 랜선으로 N개의 랜선을 만들 수 없는 경우는 없다고 가정하자. 

- 자를 때는 항상 센티미터 단위로 정수길이만큼 자른다고 가정 

- N개보다 많이 만드는 것도 N개를 만드는 것에 포함 

- 이때 만들 수 있는 최대 랜선의 길이를 구하는 프로그램 

 

 

문제 풀이

 

매개 변수 탐색(Parametric Search)

 

매개변수 탐색 (Parametric Search) (velog.io)

 

매개변수 탐색 (Parametric Search)

매개변수 탐색에 대해 알아보자

velog.io

 

[C++ Algorithm] 매개 변수 탐색(Parametric Search) — while(true) { continue; } (tistory.com)

 

[C++ Algorithm] 매개 변수 탐색(Parametric Search)

저번 게시글에서는 이분 탐색(Binary Search)에 대해서 알아보았다. (https://m42-orion.tistory.com/69) 이번 게시글에서는 전에 이야기 했던 것처럼 매개 변수 탐색(Parametric search)에 대해 알아보고자 한다.

m42-orion.tistory.com

- 이진 탐색(이분 탐색)을 사용하여 조건을 만족하는 최대값을 구하는 방법 

- 최적화 문제를 결정 문제로 바꿔서 푸는 방법

- 이진 탐색과 풀이 방식이 유사하며, 시간 복잡도는 log2(N)

 

매개변수 탐색을 사용하는 경우 

 

1) 특정 지점 이전에는 조건을 만족하지만 이후에는 조건을 만족하지 않는 경우 최댓값을 구할 때

2) 특정 지점 이전에는 조건을 만족하지 않지만 이후에는 조건을 만족하는 경우 최솟값을 구할 떄 

 

 

매개변수와 결정 함수 

 

매개변수 

 

- 찾고자 하는 최솟값 또는 최댓값이 존재하는 구간의 값

- 매개변수는 연속이어야 함 

 

결정 함수 

 

- 조건의 만족여부를 판정하는 함수 

- 문제에 제시된 조건에 따라 계산한 다음에 true 또는 false를 반환하여 조건의 만족여부를 알려줌

- 결정함수의 결과 또한 매개변수에 대해서 연속이어야 하며, 주어진 구간에 대해서 한 지점에서만 조건의 만족여부가 바뀌어야 한다. 

- 즉, 구간의 앞부분에서 만족하다가 뒷부분에서 만족하지 않거나, 구간의 앞부분에서 만족하지 않다가 뒷부분에서 만족해야 한다. 

 

문제의 매개변수 

- 최대 랜선의 길이 x

- x의 길이는 검사범위에서의 중간 값(mid)이고, 결정함수의 결과에 따라서 x를 늘리고 줄이면서 확인

- x의 범위 (1 ~ k개의 랜선들 제일 긴 길이)

 

문제의 결정 함수 

 

- "K개의 랜선을 각각 길이 x로 잘랐을 때, N개의 랜선을 만들 수 있어야 한다."로 설정

- 위의 조건을 만족하면 true를 , 만족하지 않으면 false를 반환 

 

- K개의 랜선을 각각 길이 x로 나눈 몫을 모두 더한다.

- 이 값이 n보다 크거나 같으면 조건을 만족하는 것이기 때문에 true를 반환하고, 이 값이 n보다 작으면 조건을 만족하지 못하기 때문에 false를 반환 

 

- true를 반환했다는 이야기는 랜선을 n개 이상 만들었다는 뜻이므로, 랜선의 길이 x를 좀 더 늘려봐도 된다. 

- 따라서 중간 값(mid)의 값을 더 높여야 한다. 그러므로 low = mid+1을 해준다. 

 

- false를 반환했다는 이야기는 랜선을 n개 미만 만들었다는 뜻이므로, 랜선의 길이 x를 줄여야 한다.

- 따라서 중간 값(mid)의 값을 더 낮춰야 한다. 그러므로 high = mid -1을 해준다. 

 

- 이런 방법으로 계속 진행하다가 low > high가 되는 순간, 즉 검사할 구간이 더 이상 남아있지 않는 경우 검사를 종료 

 

 

정답 

 

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;

public class Main {
    static int lansun[];
    static long max, min, mid;
    public static void main(String[] args) throws IOException
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        
        StringTokenizer st = new StringTokenizer(br.readLine());
        
        int K = Integer.parseInt(st.nextToken()); //이미 가지고 있는 랜선의 개수
        int N = Integer.parseInt(st.nextToken()); //필요한 랜선의 개수 
        
        lansun = new int[K];
        
        max = Long.MIN_VALUE;
        min = 0;
        
        for(int i=0; i<K; i++)
        {
        	st = new StringTokenizer(br.readLine());
            lansun[i] = Integer.parseInt(st.nextToken());
            max = Math.max(lansun[i],max);
        }
        max++;
        
        while(min<max)
        {
            mid = (min+max)/2;
            
            long cnt = 0;
            
            for(int i=0; i<K; i++)
            {
                cnt +=lansun[i]/mid; //각 랜선마다 몇 칸씩 나오는지 
            }
            
            if(cnt<N)
            {
                max = mid;
            }
            else
            {
                min = mid+1;
            }
        }
        
        bw.write(String.valueOf(min-1));
        
        bw.flush();
        bw.close();
        br.close();
    }
}

 

 

'Java > 백준' 카테고리의 다른 글

[JAVA] 백준 2110 공유기 설치  (0) 2024.03.13
[JAVA] 백준 2805 나무 자르기  (0) 2024.03.12
[JAVA] 백준 2740 행렬 곱셈  (0) 2024.03.08
[JAVA] 백준 11401 이항 계수 3  (3) 2024.03.08
[JAVA] 백준 1629 곱셈  (0) 2024.03.08