[소프티어] [21년 재직자 대회 본선] 코딩 테스트 세트 - JAVA
https://softeer.ai/practice/info.do?idx=1&eid=630
풀이
난이도별로 문제의 개수가 주어지고, 이 문제들을 난이도별로 하나씩 배치할때 최대 몇개의 세트가 나올 수 있는지 구하는 문제이다.
난이도는 1부터 N까지 있고, i레벨 또는 i+1레벨로 할 수 있는 문제가 있다.
각각 c와 d배열에 나누어 저장했다.
d배열의 값들을 c에 적절히 옮겨야 한다.
최댓값은 c[N]에 d[N-1]을 모두 옮겼을 때이다. 따라서 (0, c[N] + d[N-1])의 범위로 이분탐색을 통해 해당 값이 될 수 있는지 검사했다.
이분탐색으로 풀어야겠다고 생각을 못했던 문제였다.
최종 값을 이분탐색으로 찾아 체크하는 방식으로 풀 수 있구나 알게된 문제였다.
메모리: 38.74MB
시간: 380ms
언어: Java 11
코드
import java.io.*;
import java.util.*;
public class Main {
static int N;
static long[] c, d;
static long ans;
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());
int T = Integer.parseInt(st.nextToken());
StringBuilder sb = new StringBuilder();
for (int tc = 0; tc < T; tc++) {
c = new long[N];
d = new long[N - 1];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < N * 2 - 1; i++) {
if (i % 2 == 0) {
c[i / 2] = Long.parseLong(st.nextToken());
} else {
d[i / 2] = Long.parseLong(st.nextToken());
}
}
ans = 0;
binarySearch(0, d[N - 2] + c[N - 1]);
sb.append(ans).append("\n");
}
System.out.println(sb);
}
private static void binarySearch(long left, long right) {
long mid = (left + right) / 2;
long pass = 0;
boolean success = true;
for (int i = 0; i < N - 1; i++) {
long mass = c[i] + pass;
if (mass >= mid) {
pass = d[i];
continue;
} else {
mass += d[i];
pass = mass - mid;
}
if (mass < mid) {
success = false;
break;
}
}
if (c[N - 1] + pass < mid) {
success = false;
}
if (success) {
ans = mid;
if (left <= right) {
binarySearch(mid + 1, right);
}
} else {
binarySearch(left, mid - 1);
}
}
}