링크🔗
https://www.acmicpc.net/problem/1931
🗒️파이썬 코드 풀이
N = int(input())
lst = []
for _ in range(N):
start,end = map(int,input().split())
lst.append((start,end))
lst.sort()
rs_lst = [lst[0]]
for i in range(1,N):
if rs_lst[-1][1] > lst[i][0]:
if rs_lst[-1][1] > lst[i][1]:
rs_lst.pop()
rs_lst.append(lst[i])
elif rs_lst[-1][1] <= lst[i][0]:
rs_lst.append(lst[i])
print(len(rs_lst))
1. 먼저 마구잡이의 입력을 (strart 기준)정렬해준다.
2. 비교 대상을 크게 2가지로 나눈다.
1) end(현재) - strart(다음)
2) end(현재) - end(다음)
end(현재) > strart(다음)인 경우는 스케줄이 겹치는 상황이다.
이럴때는 end(현재) - end(다음)를 비교하고,
기존 스케줄을 빼고 더 작은 스케줄을 rs_lst에 넣는다.
end(현재) < strart(다음)인 경우는 겹치지 않는 새로운 스케줄이므로,
결과 리스트에 넣는다.
위의 조건을 코드로 작성 한 것이다.
if rs_lst[-1][1] > lst[i][0]: # end(현재)-strart(다음)
if rs_lst[-1][1] > lst[i][1]: # end(현재)-end(다음)
rs_lst.pop() # 기존 스케줄 제거
rs_lst.append(lst[i]) # 시간이 더 작은 스케줄 추가
elif rs_lst[-1][1] <= lst[i][0]: # end(현재)-strart(다음)
rs_lst.append(lst[i]) # 새로운 스케줄 추가
아래의 풀이를 보면 좀 더 이해하기 쉬울 것이다.
ex)
[(0, 6), (1, 4), (2, 13), (3, 5), (3, 8), (5, 7), (5, 9), (6, 10), (8, 11), (8, 12), (12, 14)]
1) (0,6) - (1,4)
endpoint 부분에 작은 값이 나오는게 무조건 유리하다.
이 경우는 기존 endpoint가 다음 endpoint보다 크기때문에,
rs_lst를 (1,4)로 새로 업데이트 해준다.
2) (1,4) - (2, 13) - (3, 5) - (3, 8)
기존 endpoint에서 다음 startpoint가 같거나 큰 경우 업데이트 한다.
이 경우는 조건에 만족하는 것들이 없어 업데이트를 안한다.
3) (5, 7)
이 경우가 기존 endpoint에서 다음 startpoint가 같거나 큰 경우다.
rs_lst에 추가로 (5, 7)를 넣어준다
🗒️다른 파이썬 코드 풀이
N = int(input())
lst = []
ans = 1
for _ in range(N):
start,end = map(int,input().split())
lst.append((start,end))
lst.sort(key=lambda x: (x[1],x[0]))
endpoint = lst[0][1]
for i in range(1,N):
if lst[i][0]>= endpoint:
endpoint = lst[i][1]
ans += 1
print(ans)
좀 더 간단하게 생각해도 된다.
endpoint가 작은게 무조건 유리하기 떄문에,
이 경우는 끝나는 시간은 기준으로 sort 해준다.
그리고 다음 startpoint가 기존 endpoint보다 큰 경우에 ans + 1을 한다.
📌 문제 코멘트
N의 크기가 100,000 이하로, 이런 경우 매우 제한된 알고리즘만 가능하다.
따라서 DFS,BFS 같은 것은 생각도 하면 안된다.
그래서 맨 처음 DP로 해결하려고 했는데, 감이 잘 안잡혔다.
DP가 안될 때는 Greedy를 생각해보고, Greedy가 안될 때는 DP를 생각해보자.
처음에는 좀 복잡했는데, 하나 하나 손으로 써보니까 감이 잡혔고,
어떤 식으로 조건을 걸어둘지 생각을 하고 코드를 작성했다.
괜히 시간을 아끼려고 바로 코드 작성하면 더 힘들어진다 ...
📚문제
한 개의 회의실이 있는데 이를 사용하고자 하는 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
힌트
(1,4), (5,7), (8,11), (12,14) 를 이용할 수 있다.
'알고리즘 > 알고리즘_백준' 카테고리의 다른 글
[Python][백준] 1449. 수리공 항승 / 정렬,그리디(S3) (3) | 2024.07.22 |
---|---|
[Python][백준] 7562. 나이트의 이동/ BFS,그래프 탐색(S1) (3) | 2024.07.22 |
[Python][백준] 2589. 보물섬 / 브루트포스,BFS (G5) (0) | 2024.07.18 |
[Python][백준] 2529. 부등호 / 브루트포스,백트래킹 (S1) (0) | 2024.07.18 |
[Python][백준] 1652. 누울 자리를 찾아라 / 구현, 문자열 (S5) (0) | 2024.07.16 |