회의실 배정

노누리·2022년 6월 9일
0

문제

한 개의 회의실이 있는데 이를 사용하고자 하는 N개의 회의에 대하여 회의실 사용표를 만들려고 한다. 각 회의 I에 대해 시작시간과 끝나는 시간이 주어져 있고, 각 회의가 겹치지 않게 하면서 회의실을 사용할 수 있는 회의의 최대 개수를 찾아보자. 단, 회의는 한번 시작하면 중간에 중단될 수 없으며 한 회의가 끝나는 것과 동시에 다음 회의가 시작될 수 있다. 회의의 시작시간과 끝나는 시간이 같을 수도 있다. 이 경우에는 시작하자마자 끝나는 것으로 생각하면 된다.

입력

첫째 줄에 회의의 수 N(1 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 N+1 줄까지 각 회의의 정보가 주어지는데 이것은 공백을 사이에 두고 회의의 시작시간과 끝나는 시간이 주어진다. 시작 시간과 끝나는 시간은 231-1보다 작거나 같은 자연수 또는 0이다.

출력

첫째 줄에 최대 사용할 수 있는 회의의 최대 개수를 출력한다.

예제 입력 1

11
1 4
3 5
0 6
5 7
3 8
5 9
6 10
8 11
8 12
2 13
12 14

예제 출력 1

4

문제 풀이

시간초과 발생한 풀이

n=int(input())
cnt=0
task=[]
time=[]

for _ in range(n):
    start,end=map(int,input().split())
    task.append((start,end))

task=sorted(task,key=lambda x:(x[1]-x[0]))

for t in task:
    if t[0] not in time and t[1] not in time:
        cnt+=1
        for i in range(t[0],t[1]+1):
            time.append(i)

print(cnt)

처음에 문제를 잘못 이해해서 최대한 사용할 수 있는 회의실의 개수를 구하는 방식을 찾고있다가 다시 문제를 읽고 최대 회의의 개수를 구하는 것임을 깨달았다.

처음에 생각한 로직은 회의 시간이 짧은 회의들 순서대로 나열한 뒤 회의실을 사용하고 있는 시간을 모두 적어 겹치는 시간이 있다면 넘어가고 겹치는 시간이 없다면 추가해주어 가능한 회의 개수를 구하는 방식이었다.

하지만 이렇게 되면 for문이 중첩되어 시간복잡도가 올라가서 시간초과가 발생하는 문제가 있었다.

아무리 생각해도 해답이 떠오르지 않아 다른 사람들의 풀이를 참고했다.


성공한 풀이

n=int(input())
cnt=0
task=[]

for _ in range(n):
    start,end=map(int,input().split())
    task.append((start,end))

task=sorted(task,key=lambda x:(x[1],x[0]))
time=0

for t in task:
    if t[0]>=time:
        cnt+=1
        time=t[1]

print(cnt)

확실히 위의 코드보다 간결해진게 눈에 보인다.

회의시간이 짧은 기준으로 정렬하기보다 먼저 끝나는 회의 순서대로 정렬을 하여 최대한 많은 회의를 할 수 있도록 찾아낸다.

같은 시간에 끝나는 회의가 있을땐 먼저 시작하는 회의를 우선순위로 해준다. 예를 들어서

[1,2]
[2,2]

이런 경우에는 [2,2]를 먼저 수행하는것보다 [1,2]를 먼저 수행하고 [2,2]를 수행하면 두 개의 회의를 할 수 있기 때문에 시작시간을 정렬 기준 두 번째로 준다.

그런 다음 처음 회의 시간부터 하나씩 비교하여 i번째 회의가 끝나는 시간보다 i+1번째 회의가 시작하는 시간이 더 이후에 있다면 겹치지 않으니 카운트를 올려준다.


답을 보고 나면 간단한데 막상 처음부터 생각하려니 떠오르지 않았다. 어떤 분이 관련 문제로 백준이 전깃줄을 말한 것을 보고 그 문제도 풀어보면서 알고리즘이랑 조금 더 친해져보려고 한다.

profile
백엔드 개발자입니다.

0개의 댓글