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

코드설명

파라매트릭 서치(ParamatricSearch) 를 활용합니다.

 

항상 파라매트릭 서치에서는 시작점과 끝점의 설정과 자료형 설정이 중요합니다.

우선 시작점의 경우, 막걸리의 음료양은 반드시 1 부터 시작합니다. 끝양은 주전자에 든 막걸리 값들 중 최대값으로 설정합니다.(이때, 2^31 - 1 로 하면되는것 아닌가? 라는 생각이 듭니다. 하지만, 제가 구현한 Optimize 코드에서는 작동하지 않습니다. 이진탐색을 어떻게 구현했느냐에 따라 달라질 수 있습니다. 사실 이 부분은 저도 명확한 구별이 어려워, 명확히 설명이 불가한 부분입니다..)

코드

정답코드입니다. 유의할점은, 막걸리의 용량은 2^31 -1 보다 작거나 같은 자연수 또는 0이다.  라는 부분입니다.

이 과정에서 mid = (left + right) / 2 일떄, left + right 가 더 해지면서 int형 범위를 벗어납니다.

그러므로 long 형을 선언합니다.

package Main;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
 
public class Main {
	static int N, M, S, P, K;
	static int answer = 0;
	static int[] arr;
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		N = Integer.parseInt(st.nextToken());
		K = Integer.parseInt(st.nextToken());
		int max = 0;
		arr = new int[N];
		for(int i=0;i<N;i++){
			st = new StringTokenizer(br.readLine());
			arr[i] = Integer.parseInt(st.nextToken());
			max = Math.max(max, arr[i]);
		}
		System.out.println(optimize(1, max));
	}
	
	static boolean isDivideable(long value) {
		
		int cnt = 0;
		for(int i=0;i<N;i++) {
			cnt += arr[i] / value;
		}
		return cnt >= K; 
	}
	static long optimize(int lo, int hi) {
		long left = lo - 1; 
		long right = hi + 1;

		while(left + 1 < right) {
			long mid = (left + right) / 2;
			if(isDivideable(mid)) {
				left = mid;
			}else {
				right = mid;
			}
		}
		return right - 1;
	}
	
}

 

만약, 탐색 횟수를 강제하고 싶을경우( 이 경우는 소수점의 정밀도 관련해서 처리할 떄 사용하는 방식입니다. )

package Main;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
 
public class Main {
	static int N, M, S, P, K;
	static int answer = 0;
	static int[] arr;
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		N = Integer.parseInt(st.nextToken());
		K = Integer.parseInt(st.nextToken());
		int max = 0;
		arr = new int[N];
		for(int i=0;i<N;i++){
			st = new StringTokenizer(br.readLine());
			arr[i] = Integer.parseInt(st.nextToken());
			max = Math.max(max, arr[i]);
		}
		System.out.println(optimize(1, max));
	}
	
	static boolean isDivideable(long value) {
		
		int cnt = 0;
		for(int i=0;i<N;i++) {
			cnt += arr[i] / value;
		}
		return cnt >= K; 
	}
	
	static long optimize(int lo, int hi) {
		long left = lo - 1; 
		long right = hi + 1;

		for(int it = 0; it < 100; it++) {
			long mid = (left + right) / 2;
			if(isDivideable(mid)) {
				left = mid;
			}else {
				right = mid;
			}
		}
		return right - 1;
	}
	
}

+ Recent posts