11000 강의실 배정
11000. 강의실 배정 / c++ / Gold 5 / 40분 / 461등
문제
https://www.acmicpc.net/problem/11000
- 강의의 시작시간과 종료시간이 주어진다.
- 강의들이 겹치지 않으면 같은 강의실에서 들을 수 있다.
- 강의실을 최소한으로 사용했을 때 그 수는?
접근 방식
그리디, 우선순위 큐, 라인 스위핑
- 처음엔 어렵게 생각해서, 해당 강의실의 강의가 끝나는 시간과 가장 가까운 시간의 다음 강의를 붙여야 한다고 생각했다.
- 하지만 그럴 필요가 없었다. 이런건 line sweeping 알고리즘이 같이 사용된다.
- 시작 시간을 기점으로, 빨리 시작하는 순으로 정렬해놓고 순회하면서, 우선순위 큐에 끝지점을 넣게된다.
- 즉, 지금 내가 처리할 강의는 남은 강의 중 ‘가장 빨리 시작하는 강의’이고, 내가 우선순위 큐에서 뽑은 강의는 처리한 강의 중 ‘가장 빨리 끝나는 강의’인 것이다.
- 이 둘을 비교했을 때, 시작시간이 끝나는 시간보다 이르다면, 새로운 강의실 하나가 필요한것이고
- 시작시간이 끝나는 시간과 같거나, 더 늦다면, 해당 강의실에서 진행할 수 있게되는 것이다. (우선순위 큐에서 pop)
문제 풀이
#pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
int N, S, T;
vector<pair<int, int>> v;
priority_queue<int, vector<int>, greater<int>> rooms;
int main()
{
ios::sync_with_stdio(0); cin.tie(0);
cin >> N;
for (int i = 0; i < N; ++i)
{
cin >> S >> T;
v.push_back({ S, T });
}
sort(v.begin(), v.end(), [](pair<int, int> A, pair<int, int> B)->bool {
if (A.first == B.first) return A.second < B.second;
return A.first < B.first;
});
rooms.push(v[0].second);
for (int i = 1; i < v.size(); ++i)
{
if (rooms.top() <= v[i].first)
{
rooms.pop();
}
rooms.push(v[i].second);
}
cout << rooms.size() << '\n';
return 0;
}
다시 생각해 볼 점
- 메모리를 줄여보려고, 배열에 넣고 정렬했던 부분을 우선순위 큐를 사용해봤는데, 오히려 메모리가 더 늘었다.
- 그리디 = 우선순위 큐, 항상 기억하자.
- 문제를 어렵게 (혹은 제대로 이해하지 못하는 경우) 보지 말자.
- 그리디는 내가 현재 처리하는 값이 항상 ‘남은 것 중 제일 ~~한 값’이라는 점을 명심하자.