BOJ 27375 금공강 사수
https://www.acmicpc.net/problem/27375
문제
윤헌이는 수강신청 시즌이 되어 시간표를 짜고 있다. 지난 학기 금요일에 수업을 들어 친구들에게 온갖 놀림을 받은 윤헌이는 이번 학기에는 꼭 금요일 공강을 지켜내기로 결심했다!!
고려대학교에서 수강할 수 있는 $n$개의 수업의 요일과 시작 교시, 끝 교시가 주어진다. 요일 $w$는 월요일부터 금요일까지 각각 1부터 5까지의 정수로 주어지며, 수업의 시작 교시 $s$, 끝 교시 $e$가 $1$부터 $10$까지의 정수로 주어진다. 수업의 학점은 $e-s+1$이다.
이번 학기에 $k$ 학점을 듣고 싶은 윤헌이는 금요일에 공강이 있는 시간표의 가짓수가 궁금하다.
이때, 같은 요일, 같은 교시에 열리는 두 수업은 동시에 수강할 수 없다. 예를 들어, 화요일 $5$교시부터 $7$교시까지 열리는 수업과 화요일 $7$교시부터 $9$교시까지 열리는 수업은 동시에 수강할 수 없다.
윤헌이를 위해 정확히 $k$ 학점을 들으면서 금요일에 수업이 하나도 없는 시간표의 가짓수를 구해 보자!
입력
첫 줄에 수강 가능한 수업의 개수 $n$과 윤헌이가 듣고 싶은 학점 $k$가 공백으로 구분되어 주어진다.
다음 $i$번째 줄에는 $i$번 수업의 요일, 시작 교시, 끝 교시 $w_i, s_i, e_i$가 공백으로 구분되어 주어진다.
출력
정확히 $k$ 학점을 들으면서 금요일에 수업이 하나도 없는 시간표의 가짓수를 출력한다.
제한
- $1 \le n \le 20$
- $1 \le k \le 22$
- $1 \le w_i \le 5$
- $1 \le s_i \le e_i \le 10$
예제 입력 1
10 15 3 4 4 3 4 9 3 6 8 1 10 10 3 2 5 2 6 10 5 5 5 2 5 7 3 6 10 3 1 6
예제 출력 1
1
4번 수업, 5번 수업, 6번 수업, 9번 수업을 들으면 1+4+5+5=15학점을 들을 수 있다. 그 이외의 경우는 불가능하다.
코드
요즘 은근히 정리할 내용이 많아서 간단한 문제만 풀고 있다…
이번 문제도 간단한 브루트포스 문제다.
코드도 딱히 주목해볼만한 부분 없이 무난한 것 같다.
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static class Lecture {
int w;
int s;
int e;
int credits;
public Lecture(int w, int s, int e, int credits) {
this.w = w;
this.s = s;
this.e = e;
this.credits = credits;
}
}
static int n;
static int k;
static int count = 0;
static List<Lecture> lectures = new ArrayList<>();
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
k = Integer.parseInt(st.nextToken());
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
int w = Integer.parseInt(st.nextToken());
int s = Integer.parseInt(st.nextToken());
int e = Integer.parseInt(st.nextToken());
int credits = e - s + 1;
// 수업의 학점이 k보다 크지 않고, 금요일에 진행되는 것이 아니면 추가
if(w != 5 && credits <= k) {
lectures.add(new Lecture(w, s, e, credits));
}
}
// 요일을 기준으로 오름차순, 요일이 같으면 끝 교시를 기준으로 오름차순 정렬
lectures.sort((l1, l2) -> {
if (l1.w == l2.w) {
return l1.e - l2.e;
}
return l1.w - l2.w;
});
for (int i = 0; i < lectures.size(); i++) {
Lecture check = lectures.get(i);
countCases(i, check.w, check.e, check.credits);
}
System.out.println(count);
}
static void countCases(int lecture, int lastW, int lastEnd, int credits) {
if(credits == k) {
count++;
return;
}
for (int i = lecture + 1; i < lectures.size(); i++) {
Lecture check = lectures.get(i);
int creditsSum = credits + check.credits;
// 현재 검사 중인 수업을 수강할 수 없거나, 수강했을 때의 총 학점이 k보다 크면 현재 수업 생략
if(creditsSum > k || check.w == lastW && check.s <= lastEnd) {
continue;
}
countCases(i, check.w, check.e, creditsSum);
}
}
}