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]) {
위 코드를 통해 만약 종료시간이 같다면 시작시간이 더 작은애를 앞에 둬서 최대한 더 많은 시간대가 회의실을 쓰게 해준다. 왜 굳이 더 작은애를 앞에 두냐고 말한다면
이 코드들 때문이다. 우선 기준이 되는 첫번째 종료시간을 설정하고
시작시간이 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 해줘야함!
'알고리즘 > 그리디' 카테고리의 다른 글
[java 백준] 실버 2/ 1541번 잃어버린 괄호 (0) | 2022.02.15 |
---|---|
[java 백준]골드 4/ 1744번 수묶기 (0) | 2022.02.11 |
[java 백준] 실버 4/ 1783번 병든 나이트 (0) | 2022.02.06 |
[java 백준] 실버 5/ 10610번 30 (0) | 2021.11.04 |
[java 백준]브론즈 3/ 2875번 대회 or 인턴 (0) | 2021.09.19 |
댓글