ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 1561 놀이공원
    ALGORITHM/BOJ 2021. 2. 13. 22:32

    www.acmicpc.net/problem/1561

     

    1561번: 놀이 공원

    첫째 줄에 N(1 ≤ N ≤ 2,000,000,000)과 M(1 ≤ M ≤ 10,000)이 빈칸을 사이에 두고 주어진다. 둘째 줄에는 각 놀이기구의 운행 시간을 나타내는 M개의 자연수가 순서대로 주어진다. 운행 시간은 1 이상 30

    www.acmicpc.net

    2021-02-13


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.StringTokenizer;
     
    public class Main1561 {
        public static int M, arr[], answer;
        public static long N;
        public static long sum(long mid) { // 현재 분 수에서의 아이들의 총합
            long ans = 0;
            for(int i = 0; i < M; i++) ans += mid / arr[i]; // (분 수) / (놀이기구 운행시간)
            return ans+M; // 0분(+M)
        }
     
        public static int calc(long cur, long mid) { // cur : (mid-1)분의 아이들 총 수 + 1
            for(int i = 0; i < M; i++) {
                if(mid % arr[i] == 0) { // 0으로 나누어 떨어지는 경우는 아이들이 놀이기구를 탑승하는 경우
                    if(cur == N) return i; // 찾고자 하는 아이가 타는 놀이기구 번호를 알게 되면 return
                    else cur++;
                }
            }
            return -1// 못 찾은 경우
        }
     
        public static void search() {
            long start = 1;
            long end = 2000000000L*30L; // end값은 N*M으로 잡아햔다.
     
            while(start <= end) {
                long mid = (start + end) >> 1;
                long next = sum(mid); // 현재 분 수에서 아이들의 총합
                if(N <= next) { // 구하려는 번호보다 아이들의 총합이 더 크거나 같은 경우
                    int ans = calc(sum(mid-1)+1, mid); // 현재 (분 수의 -1분)의 아이들의 총합 +1이 현재 분 수의 시작 분 수
                    if(ans == -1) end = mid - 1// 만약 N을 못 찾았다면
                    else { // 찾았다면
                        answer = ans+1;
                        break;
                    }
                }
                else start = mid +1;
            }
        }
        public static void main(String[] args) throws Exception{
            BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
            StringTokenizer st = new StringTokenizer(bf.readLine());
            N = Long.parseLong(st.nextToken());
            M = Integer.parseInt(st.nextToken());
            arr = new int[M];
            answer = 0;
            st= new StringTokenizer(bf.readLine());
            for(int i = 0; i < M; i++) {
                arr[i] = Integer.parseInt(st.nextToken());
            }
            if(N <= M) answer = (int) N; // N <= M보다 작은 경우는 그냥 N이 답이다.
            else search();
            System.out.println(answer);
        }
    }
     
    cs

    #문제풀이

    코드에 주석으로 자세하게 썼다.

     

    처음에 다른 이분탐색 문제처럼 눈에 확 들어오지 않았다. 포인트는 분을 기준으로 현재 탑승한 아이들의 총합을 구하는 것이었다.

     

    1) N <= M인 경우를 처음에 생각하지 못해서 틀렸었다. 

     

    2) right값을 처음에 단순히 입력값으로 들어온 N*M으로 잡아서 계속 틀렸었다. 2000000000L*30L으로 잡으니 통과되었다.

    'ALGORITHM > BOJ' 카테고리의 다른 글

    [백준] 3649 로봇 프로젝트  (0) 2021.02.18
    [백준] 1062 가르침  (0) 2021.02.15
    [백준] 5676 음주 코딩  (0) 2021.02.07
    [백준] 14425 문자열 집합  (0) 2021.02.02
    [백준] 1238 파티  (0) 2021.01.31

    댓글

Programming Diary