알고리즘/이진탐색
[백준] 장난감 경주 19592번
HYJJ
2022. 1. 29. 17:21
문제 링크 : https://www.acmicpc.net/problem/19592
이진 탐색으로 얼만큼의 최대 부스터를 사용할지 정하는 문제이다.
부스터의 길이를 이진 탐색 대상으로 놓고 코드를 작성해보았다.
package baekjoon;
import java.util.Scanner;
public class ToyCompetition_19592 {
private static int solved(int N, int X, int Y, int v[]) {
double arr[] = new double[v.length];
double min = X;
//나머지 배열 중 가장 적은 값 찾아내기 (소수점 자리 안버리고)
for(int i=0; i<v.length; i++) {
arr[i] = X/v[i];
if(min>arr[i]) {
min = arr[i];
}
}
if(min==arr[v.length-1]){
return 0;
}
//이진탐색으로 찾아내기
int start = 1;
int end = Y;
int mid;
//몇 초 걸리는지
double tmp;
while(start<=end) {
// mid : 부스터 속력
mid = (start+end)/2;
// tmp : 부스터를 사용하였을 때에 걸리는 시간.
tmp = (12-mid)/v[v.length-1];
if(min < tmp) {
// 반으로 나눴을 때, 오른쪽에 있는 경우 (부스터를 썼음에도 여전히 1등 못한 경우)
start = mid + 1;
// System.out.println(start+" "+end);
} else if(min > tmp) {
// 부스터를 썼을 때 1등한 경우 (그럼에도 최소 수치를 찾아야 함.)
end = mid;
// System.out.println(start+", "+end);
} else {
return mid + 1;
}
}
return -1;
}
public static void main(String[] args) {
// Scanner sc = new Scanner(System.in);
int n = 3;
int x = 12;
int y = 11;
int vec[] = {3,2,1};
int ans = solved(n,x,y,vec);
System.out.println(ans);
//scanner
// int T = sc.nextInt();
// int vec[] = new int[3];
// for(int i=0; i<T;i++) {
// int N = sc.nextInt();
// int X = sc.nextInt();
// int Y = sc.nextInt();
//
// for(int j=0; j<3; j++) {
// vec[j] = sc.nextInt();
// }
// }
// sc.close();
}
}
일단 처음 작성했을 때의 문제는
1. 정답이 출력되지 않은 것 (사실 틀렸다고 보면 됨.)
2. 나누기로 계산을 하기 때문에 소수점으로 딱 떨어지지 않는 경우 마지막 else 구문에서 애매해질 수 있다는 점이다.
3. 공동 우승일 때의 경우 고려
고민을 해보고 다시 이진 탐색을 손코딩 했을 때, 문제를 읽는 과정에서 잘못 파악한 것을 확인했다.
Y m/s 만큼 1초간 이동한 것이기 때문에 tmp 변수에 값을 넣어줄 때 +1을 해줘야 했다! (1번 해결)
3번의 경우도 더불어서 다시 생각해봤다.
if(min < tmp) {
// 반으로 나눴을 때, 오른쪽에 있는 경우 (부스터를 썼음에도 여전히 1등 못한 경우)
start = mid + 1;
} else if(min > tmp) {
// 부스터를 썼을 때 1등한 경우 (그럼에도 최소 수치를 찾아야 함.)
end = mid;
} else {
return mid + 1;
}
else 조건은 v[i]를 제외한 나머지 장난감 중에서 가장 적게 걸리는 시간을 min 변수에 넣은건데
min과 tmp가 같다는 것은 공동우승한다는 것이다. (공동 우승의 경우를 생각 안함.)
mid+1을 리턴하는게 답이 될 수 있을까?
else 조건(min==temp)에서 다시 if 문을 추가해보았다.
else {
if(mid==Y)
break;
else
return mid+1;
}
최대로 쓸 수 있는 부스터 속력은 Y로 만약 찾고자하는 mid가 Y랑 같다는 조건을 추가하였다.
이렇게 추가하면 break로 while문에서 빠져나와 -1을 리턴한다.
2번의 경우가 조금 복잡했다.
처음에는 if와 else if로 넘어가는 순간의 값을 찾아야 한다고 생각했다.
조금 더 고민하다가 수정해서 올리겠다.