본문 바로가기
알고리즘/그리디

[java 백준] 실버 2/1931번 회의실 배정

by Meaning_ 2022. 2. 8.
728x90
반응형

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

 

1931번: 회의실 배정

(1,4), (5,7), (8,11), (12,14) 를 이용할 수 있다.

www.acmicpc.net

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;
 
public class Main {
    public static int n;
    public static int cnt;
    public static int[][] arr;
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        n = Integer.parseInt(br.readLine());
        arr = new int[n][2];
        StringTokenizer st;
        for (int i = 0; i < n; i++) {
            st = new StringTokenizer(br.readLine());
            arr[i][0= Integer.parseInt(st.nextToken());
            arr[i][1= Integer.parseInt(st.nextToken());
 
        }
 
        // 종료시간을 기준으로 정렬
        // 나는 시작시간을 기준으로 정렬했고, comparator생각도 못함
        Arrays.sort(arr, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                if (o1[1== o2[1]) {
                    // 종료시간이 같을 경우 시작시간이 더 빠른 애
                    return Integer.compare(o1[0], o2[0]);
                }
                return Integer.compare(o1[1], o2[1]);
            }
        });
        int std = arr[0][1];
        int cnt = 1;
        for (int i = 1; i < n; i++) {
            if (arr[i][0>= std) {
                // 어차피 정렬되어있어서 상관없음
                cnt++;
                std = arr[i][1];
            }
        }
        System.out.println(cnt);
 
    }
 
}
cs

 

문제를 풀면서 중요한 점은 종료시간을 기준으로 정렬하는 것과 comparator을 써주는 것이다.

난 처음에 시작시간을 기준+comparator을 쓰지 않았더니 (1,1) (2,2)와 같은 시작과 끝이 같은 경우에 손을 쓸 수 가 없었다.

 

우선 종료시간을 기준으로 정렬해야하는 이유는

결국 종료시간이 작아야 최대한 많이 회의실 스케쥴을 배정할 수 있기 때문이다. 아무리 오름차순을 기준으로 해도 결국 시작의 기준이 되는 애는 (0,6)이 아니라 (1,4)였다. 그런데 (1,4)가 종료를 기준으로 하면 가장 선두에 있다. 그러니 얘가 시작값, 즉 standard가 될 수 있는 것이다. 

그리고 예제에 주어진걸 봐도 시작시간을 들쭉날쭉한데 종료시간은 오름차순으로 정렬되어있는 것을 알 수 있다.

 

comparator을 써주는 것은 시작과 끝이 같은 경우를 살리기 위함이다. 처음엔 array말고 hashmap, arraylist를 이용해보기도 했는데 그냥 array에 comparator써주는 것이 시작이 같은 경우, 끝이 같은 경우 또는 둘 다 같은 경우에 그 원소를 살리는데 제격이였다. 나머지는 한쪽이라도 중복되면 원소가 사라져서 골치아팠다.

if (o1[1== o2[1]) {

                    // 종료시간이 같을 경우 시작시간이 더 빠른 애
                    return Integer.compare(o1[0], o2[0]);
                }

위 코드를 통해 만약 종료시간이 같다면 시작시간이 더 작은애를 앞에 둬서 최대한 더 많은 시간대가 회의실을 쓰게 해준다. 왜 굳이 더 작은애를 앞에 두냐고 말한다면

 

int std = arr[0][1];
        int cnt = 1;
        for (int i = 1; i < n; i++) {
            if (arr[i][0>= std) {
                // 어차피 정렬되어있어서 상관없음
                cnt++;
                std = arr[i][1];
            }
        }

이 코드들 때문이다. 우선 기준이 되는 첫번째 종료시간을 설정하고 

시작시간이 std보다 크면 그 시작시간에 해당하는 종료시간이 std가 되는 형태로 코드를 짜봤다. 여기서 종료시간이 같다면 시작시간이 더 작은애를 앞에 두는 이유를 설명할 수 있다.

std는 반복문을 통해 arr[i][0]이 자기보다 큰지 작은지 비교하는데 만약에 종료시간이 같은데 시작시간이 더 작은애가 뒤에 있다면 얘랑 비교하는걸 놓칠 수도 있기 때문이다.

 

예를 들어

 

1 4

3 5

0 6

7 7

5 7

이 있다고 해보자. 종료시간만 정렬되어있다면

 

 

1 4

3 5

0 6

7 7

5 7일테고

여기서는 (1,4)  (7,7)만 탐색하고 끝낼거지만

 

종료시간이 같을 때 시작시간도 같이 고려해준다면

1 4

3 5

0 6

5 7

7 7로 정렬되기 때문에 (1,4) (5,7) (7,7) 총 3가지 경우가 생긴다. 

 

기억해야할 것 

배열 안에 있는 원소 Comparator를 이용해 비교시

 

Arrays.sort(arr,new Comparator<int[]>(){

 

});

반드시 import java.util.Comparator 해줘야함!

728x90
반응형

댓글