백준 1931번 (회의실 배정, C++, priority_queue) / 추가 반례 [BAEKJOON]

회의실 배정

www.acmicpc.net/problem/1931

시간 제한메모리 제한제출정답맞힌 사람정답 비율
2 초128 MB144010450433183429.573%

문제

한 개의 회의 실이 있는데 이를 사용하고자 하는 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) 를 이용할 수 있다.

출처

알고리즘 분류


추가 예제

예제 입력 A

5
6 7
6 6
5 6
5 5
7 7

예제 출력 A

5

예제 입력 B

5
5 5
5 6
6 6
6 7
7 7

예제 출력 B

5

예제 입력 C

3
1 1
1 1
0 1

예제 출력 C

3

예제 입력 D

2
1 4
3 3

예제 출력 D

1

예제 입력 E

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

예제 출력 E

8

한 개의 회의실
N개의 회의
회의는 시작 시간과 끝나는 시간이 주어짐
회의 실을 사용할 수 있는 회의의 최대 개수를 구하는 문제

회의는 한번 시작하면 중간에 중단될 수 없음
한 회의가 끝나는 것과 동시에 다음 회의가 시작
회의의 시작 시간과 끝나는 시간이 같을 수 있음 (시작과 동시에 끝남)

회의가 끝나는 시간을 기준으로 가장 낮은 회의를 선택하고
선택한 회의의 끝나는 시간보다 일찍 시작하는
회의를 리스트에서 제외하면 될 것 같다.
자료 구조는 priority_queue 를 사용하면 될 것 같다.
범위도 (2^31) -1이라서 int 내에서 해결 가능

데이터 확인

11
5 9
6 10
3 5
0 6
5 7
8 11
8 12
2 13
1 4
3 8
12 14
#include <iostream>
#include <queue>

using namespace std;
priority_queue < pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> myQueue;

int result = 0;
int startLecture = 0;
int endLecture = 0;

void Initializtion()
{

	cin >> result;
	int N = result;

	while (N > 0)
	{
		cin >> startLecture >> endLecture;
		// 강의가 끝나는 시간을 낮은 값으로 정렬
		myQueue.push(make_pair(endLecture, startLecture));
		N--;
	}

}

int main()
{
	Initializtion();

	while (!myQueue.empty())
	{
		endLecture = myQueue.top().first;
		startLecture = myQueue.top().second;
		myQueue.pop();
		cout << " LectureEnd : " << endLecture << " startLecture : " << startLecture << "\n";
	}

	return 0;
}

이제 회의가 끝나는 시간을 기준으로 가장 낮은 회의를 선택하고
선택한 회의의 끝나는 시간보다 일찍 시작하는 회의를 리스트에서 제외하면 될 것 같다.

#include <iostream>
#include <queue>

using namespace std;
priority_queue < pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> myQueue, myQueue2;

int result = 0;
int startLecture = 0;
int endLecture = 0;
int N = 0;

void Initializtion()
{
	cin >> N;
	while (N > 0)
	{
		cin >> startLecture >> endLecture;
		// 강의가 끝나는 시간을 낮은 값으로 정렬
		myQueue.push(make_pair(endLecture, startLecture));
		N--;
	}

}

int main()
{
	Initializtion();
	pair<int, int> temp;

	while (!myQueue.empty())
	{

		// 강의가 끝나는 시간
		endLecture = myQueue.top().first;
		//cout << " 등록된 강의 : " << "myQueue.top().first : " << myQueue.top().first << " myQueue.top().second : " << myQueue.top().second << "\n";
		myQueue.pop();
		result++;
		// pair 끝나는 시간 / 시작 시간
		while (!myQueue.empty())
		{
			temp = make_pair(myQueue.top().first, myQueue.top().second);
			myQueue.pop();
			//cout << " 시작시간 :  " << temp.second << " 끝나는 시간 : " << temp.first << "\n";
			if (temp.second < endLecture)
			{

			}
			else
			{
				myQueue2.push(temp);
			}
	
		}
		myQueue = myQueue2;
		myQueue2 = priority_queue < pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>>();
	}
	cout << result;
	return 0;
}

틀린 코드

#include <iostream>
#include <queue>

using namespace std;

priority_queue < pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> myQueue, myQueue2;

int result = 0;
int startLecture = 0;
int endLecture = 0;
int N = 0;

void Initializtion()
{
	cin >> N;
	while (N > 0)
	{
		cin >> startLecture >> endLecture;
		myQueue.push(make_pair(endLecture, startLecture));
		N--;
	}

}

int main()
{
	Initializtion();
	while (!myQueue.empty())
	{
		endLecture = myQueue.top().first;
		myQueue.pop();
		result++;
		myQueue2 = myQueue;
		myQueue = priority_queue < pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>>();
		while (!myQueue2.empty())
		{
			// 다음 강의는 지금 강의가 끝나는 시간보다 같거나 커야함
			if (myQueue2.top().second >= endLecture)
			{
				myQueue.push(myQueue2.top());
			}

			myQueue2.pop();
		}
	}
	cout << result;
	return 0;
}

시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과 시간 초과

더 유연한 생각이 필요하다


아마 큐에 다시 넣는 부분이 문제인 것 같다.
테스트 케이스는 맞으나 시간 초과로 고통 받는다.
이 방법은 버리기로 함
멀티 맵으로 바꾸는 것이 좋은 방법인 것 같다. => (무슨 정신 머리로 이런 생각을 했는지 의문)

계속되는 실패에 처음으로 돌아감

고민하다
계속 큐에 넣어야 하는가?????
너무 비효율적이다 생각
int로 현재 강의가 끝나는 지점만 알면 되는 것 아닌가????

통과된 코드

#include <iostream>
#include <queue>

using namespace std;

// 우선 큐로 정렬 강의가 끝나느 시간을 오름차순으로 정렬
priority_queue < pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> myQueue;

int result = 0;
int startLecture = 0;
int endLecture = 0;
int N = 0;

// 조건 초기화
void Initializtion()
{
	cin >> N;
	while (N > 0)
	{
		cin >> startLecture >> endLecture;
		myQueue.push(make_pair(endLecture, startLecture));
		N--;
	}
}


int main()
{
	Initializtion();

	// 현재 진행 중인 강의가 끝나는 시간으로 생각
	int curEndLecture = 0;

	// 끝나는 시간이 가장 빠른 강의를 가져옴
	curEndLecture = myQueue.top().first;
	myQueue.pop();
	result++;

	// 주어진 강의를 모두 확인할 때까지 반복
	while (!myQueue.empty())
	{
		endLecture = myQueue.top().first;
		startLecture = myQueue.top().second;
		myQueue.pop();

		// 끝나는 시간이 빠른 강의 들의 시작 시간을 확인 
		// 강의의 시작 시간이 끝나는 시간과 같거나 늦으면
		// 현재 진행 중인 강의의 인덱스를 바꾸어줌
		// (강의를 진행한다는 의미)
		if (startLecture >= curEndLecture)
		{
			curEndLecture = endLecture;
			result++;
		}
	}

	cout << result;
	return 0;
}

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤