[백준 9007] 카누 선수 (JAVA)

solser12·2021년 9월 30일
0

Algorithm

목록 보기
20/56

문제


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

풀이


일반적인 완탐으로 풀 때 최악의 경우 1000^4 으로 시간초과가 발생합니다.

그래서 1, 2반을 더하는 모든 수(n^2)와 3, 4반을 더하는 모든 수(n^2)를 구한 다음 1, 2반에서 하나를 선택 후 3, 4반에서 이분탐색을 이용하면 n^2logn^2으로 해결할 수 있습니다.

코드


package BOJ;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main_9007_카누선수 {

    static int k, n;

    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        StringTokenizer st;


        int T = Integer.parseInt(br.readLine());
        for (int t = 1; t <= T; t++) {
            st = new StringTokenizer(br.readLine());
            k = Integer.parseInt(st.nextToken());
            n = Integer.parseInt(st.nextToken());

            int[][] group = new int[4][n];

            for (int i = 0; i < 4 ; i++) {
                st = new StringTokenizer(br.readLine());
                for (int j = 0; j < n; j++) {
                    group[i][j] = Integer.parseInt(st.nextToken());
                }
            }

            int[][] calcGroup = new int[2][n*n];
            int index = 0;
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    calcGroup[0][index] = group[0][i] + group[1][j];
                    calcGroup[1][index++] = group[2][i] + group[3][j];
                }
            }

            Arrays.sort(calcGroup[0]);
            Arrays.sort(calcGroup[1]);

            sb.append(k - find(calcGroup[0], calcGroup[1])).append('\n');
        }

        System.out.println(sb);
        br.close();
    }

    public static int find(int[] first, int[] second) {

        int ans = 0, min = Integer.MAX_VALUE;
        for (int i : first) {
            int result = binarySearch(second, k - i);
            int abs = Math.abs(result);

            if (min > abs) {
                ans = result;
                min = abs;
            } else if (min == abs && ans < 0) {
                ans = result;
            }
        }

        return ans;
    }
    public static int binarySearch(int[] arr, int num) {

        int result = 0, min = Integer.MAX_VALUE;
        int left = 0, right = arr.length - 1;
        while (left <= right) {
            int mid = (left + right) >> 1;

            int calc = num - arr[mid];
            int abs = Math.abs(calc);

            if (min > abs) {
                min = abs;
                result = calc;
            } else if (min == abs && result < 0) {
                result = calc;
            }

            if (calc > 0) {
                left = mid + 1;
            } else if (calc < 0) {
                right = mid - 1;
            } else {
                return 0;
            }
        }

        return result;
    }
}
profile
더 나은 방법을 생각하고 고민합니다.

0개의 댓글