ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] 백준 1931 회의실 배정
    Programming/Algorithm 2021. 3. 24. 01:47

     

    문제

    회의의 시작시간, 종료시간이 주어질 때 사용할 수 있는 회의의 최대개수를 출력하는 문제.

     

     

    풀이 

    - 처음엔 문제를 잘못 이해했다.

       - 시작시간이 2 종료시간이 2라고 할 때 시작과 동시에 끝나므로 해당 경우도 갯수에 더해줘야 한다.

       - 또한 (1 2) (2 2) 인 경우나 (2 2) (2 5) 인 경우 2 회의 모두 결과값에 포함될 수 있다.

    - 첫번째로 푼 풀이는 다이나믹 프로그래밍이었다.

       - 현재 인덱스에 대해서 이전의 인덱스를 모두 확인하여 최댓값을 구하게끔 했다.

       - 이 경우 O(n^2)이라는 시간 복잡도가 나와 N이 10만인 경우 100억의 연산이 필요하다는 문제가 있었다. 당연히 시간초과가 났다. 

    - 두번째로 푼 풀이는 그리디였다.

        - 사실 회의를 최대한으로 하는 횟수는 매우 간단하게 구할 수 있다.

        - 회의가 빨리 끝나는 것을 기준으로 정렬한 뒤에 0번째 회의부터 더해나가는 것이다.

        - 이 로직을 사용하면 O(N)에 풀이할 수 있다.

     

     

     

    코드

     

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.*;
    
    public class b1931 {
    
        static class Schedule {
            int start, end;
    
            public Schedule(int start, int end) {
                this.start = start;
                this.end = end;
            }
    
            @Override
            public String toString() {
                return "Schedule{" +
                        "start=" + start +
                        ", end=" + end +
                        '}';
            }
        }
    
        public static void main(String[] args) throws IOException {
    //        wrongAnswer();
            solution2();
        }
    
        /* 그리디 [8:00~]
         - 끝나는 시간을 기준으로 오름차순 정렬한 뒤에
         - 차례로 구하면 탐욕법으로 최대 개수를 구할 수 있다.
    
         - 다음과 같은 경우 답은 3이다.
        3
        2 2
        1 2
        2 3
        */
        static void solution2() throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            int N = Integer.parseInt(br.readLine());
            ArrayList<Schedule> list = new ArrayList<>();
            for (int i = 0; i < N; i++) {
                StringTokenizer st = new StringTokenizer(br.readLine());
                int start = Integer.parseInt(st.nextToken());
                int end = Integer.parseInt(st.nextToken());
                list.add(new Schedule(start, end));
            }
            Collections.sort(list, new Comparator<Schedule>() {
                @Override
                public int compare(Schedule o1, Schedule o2) {
                    if (o1.end != o2.end)
                        return o1.end > o2.end ? 1 : o1.end == o2.end ? 0 : -1;
                    return o1.start > o2.start ? 1 : o1.start == o2.start ? 0 : -1;
                }
            });
    
            int cnt = 1;
            int prev_end = list.get(0).end;
            for (int i = 1; i < N; i++) {
                if (prev_end <= list.get(i).start) {
                    cnt++;
                    prev_end = list.get(i).end;
                }
            }
    
            System.out.println(cnt);
        }
    
        // 다이나믹 프로그래밍 풀이 : 시간초과
        // - 현재 배열방에 대해서 그 전 배열방을 모두 탐색하며 최솟값을 찾아간다.
        // - O(N^2) => O(100_000 * 100_000) => O(10_000_000_000) 100억
        static void wrongAnswer() throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            int N = Integer.parseInt(br.readLine());
    
            ArrayList<Schedule> list = new ArrayList<>();
            for (int i = 0; i < N; i++) {
                StringTokenizer st = new StringTokenizer(br.readLine());
                int start = Integer.parseInt(st.nextToken());
                int end = Integer.parseInt(st.nextToken());
                list.add(new Schedule(start, end));
            }
            Collections.sort(list, new Comparator<Schedule>() {
                @Override
                public int compare(Schedule o1, Schedule o2) {
                    if (o1.start == o2.start) {
                        return o1.end > o2.end ? 1 : (o1.end == o2.end ? 0 : -1);
                    }
                    return o1.start > o2.start ? 1 : -1;
                }
            });
    
            int[] dp = new int[N]; // N번째 회의까지 최대 개수
            Arrays.fill(dp, 1);
            for (int i = 1; i < N; i++) { // 기준
                for (int j = i - 1; j >= 0; j--) { // 탐색 인덱스
                    int nextStart = list.get(i).start;
                    int prevStart = list.get(j).start;
                    int prevEnd = list.get(j).end;
                    if (dp[i] <= dp[j]
                            && nextStart >= prevEnd && prevStart != prevEnd) {
                        dp[i] = dp[j] + 1;
                    }
                }
            }
    
            System.out.println(Arrays.stream(dp).max().getAsInt());
        }
    }
    

     

     

     

    'Programming > Algorithm' 카테고리의 다른 글

    [Java] 백준 1003 피보나치 함수  (0) 2021.03.24
    [Java] 백준 12852 1로 만들기 2  (0) 2021.03.24
    [Java] 백준 11726 2 x n 타일링  (0) 2021.03.19
    [Java] 백준 11399 ATM  (0) 2021.03.19
    [Java] 백준 1149 RGB 거리  (0) 2021.03.16

    댓글

Designed by black7375.