포스트

Pr.1931 회의실배정

Pr.1931 회의실배정

문제

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

입력

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

출력

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

예제 입력

1
2
3
4
5
6
7
8
9
10
11
12
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. 시간 복잡도, 공간 복잡도
    • 시간복잡도 : N이 100 이므로 최악의 시간 복잡도 100! -> 단순구현 불가
    • 공간복잡도 : 100 이므로 벡터 n(100)의 복잡도
  2. 최대, 최소 조건
    • n의 길이 : 100
    • 시간 : 1,000,000
  3. 사용 알고리즘
    • 정렬을 통한 그리디
    • 도착 시간 기준으로 정렬
    • 현재시간과 도착시간을 비교
    • 현재시간 > 도착시간 : 현재시간 + 검사시간
    • 현재시간 < 도착시가 : 도착시간 + 검사시간
  4. 반례, 경계값

제출 코드

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
#include <bits/stdc++.h>
using namespace std;

int n, arrive, test, res;
vector<pair<int, int>> v;

int main(){
  cin >> n;
  for (int i = 0; i < n; i++){
    cin >> arrive >> test;
    v.push_back({arrive, test});
  }
  sort(v.begin(), v.end());

  for (int i = 0; i < n; i++){
    if (res < v[i].first){
      res = v[i].first + v[i].second;
    }
    else{
      res += v[i].second;
    }
  }
  cout << res << '\n';
  return 0;
}

해설

생각해볼 점

정답 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<bits/stdc++.h>

using namespace std;
int n;
int main(){
	cin >> n; 
	vector<pair<int,int>> a(n);
	for(int i =0; i < n; i++) cin >> a[i].first >> a[i].second;
	sort(a.begin(),a.end()); 
	int realTime = a[0].first + a[0].second;
	for(int i = 1; i < a.size(); i++){
		realTime = max(realTime, a[i].first);
		realTime += a[i].second;
	}
	cout << realTime << "\n"; 
    return 0;
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.