728x90

요약: 시작시간과 끝나는 시간이 주어지는 N개의 회의가 있을 때 하나의 회의실에 최대로 많이 넣을 수 있는 회의의 개수를 구하는 문제입니다. 

 

설명: 일찍 끝나는 회의 순으로 정렬한 후, 순서대로 회의실이 비어있으면 회의를 집어넣으면 됩니다. 끝나는 시간을 기준으로 했던 이유를 보여주는 예시) 1~10시 까지 회의, 2~4시 까지의 회의, 4~5시 까지의 회의 가 있으면 1~10시까지의 회의 보다 나머지 두 개의 회의를 넣는게 더 이득이다.

 

#include <bits/stdc++.h> // 모든 표준 라이브러리 헤더들을 가져오는 전처리문
using namespace std; // std라는 namespace에서 사용하려고 한다. 그냥 암기하면 됨

// 구조체 Time 선언
struct Time {
   int start_time;
   int end_time;
};

/*
   정렬의 기준을 정의한다. (사용자 정의로 customizing해서 쓸 수 있음)
   임의의 두 Time 구조체끼리 비교할 때, 
      swap을 해서 위치를 바꿀 건지(false, 즉 현재 조건을 만족하지 않음), 그대로 둘건지(true, 현재 조건을 만족함)를 리턴한다.
*/
bool compare(Time t1, Time t2) { 
   if (t1.end_time == t2.end_time) { // t1의 종료 시간(end_time)과 t2의 종료 시간(end_time)이 같다면. 
      return t1.start_time < t2.start_time; // t1의 시작 시간(start_time) < t2의 시작 시간(start_time) 조건의 결과값(true 또는 false)을 리턴한다. (즉, 오름차순으로 정렬하게 된다.)
   }
   // 그렇지 않은 경우(즉, t1과 t2의 종료 시간이 다른 경우)
   return t1.end_time < t2.end_time; // t1의 종료시간 < t2의 종료시간 조건을 리턴한다. (즉, 오름차순으로 정렬하게 됨)
}

/*
   문제:
      n개의 회의가 주어지고, 각 회의는 시작 시간과 지속 시간이 있다. (당연히 종료시간=시작시간+지속시간이다.)
      회의실이 1개일 때, 최대한 많은 회의를 커버하고 싶다. 이 때 최대 회의 수는?

   솔루션:
      일찍 끝나는 회의 순으로 정렬한 후, 순서대로 sweeping하면서 선택한다.
      (구글에 "회의실 문제" 또는 "회의실 배정 문제"로 검색하면, 자세한 설명들이 있다.)
      (참고로, 이 문제는 욕심쟁이 기법(greedy) 알고리즘의 가장 대표적인 문제이다.)
*/
int maxEvents(vector<int> arrival, vector<int> duration) {
   int n = arrival.size(); // 회의 갯수를 n에 저장

   /*
      각 element의 타입이 구조체 Time인 벡터 times를 선언. 크기는 n
      구조체 Time을 선언해서 새로운 벡터를 만드는 이유:
         원래 문제에서는 시작 시간 arrival, 지속 시간 duration가 매개변수로 주어지는데, 
         구조체로 묶어서 (시작 시간, 종료 시간) 형태로 바꿔서 저장하면, sort할 때 편하다.
   */
   vector<Time> times(n);
   for (int i=0; i<n; i++) { // n개를 훑으면서
      times[i].start_time = arrival[i]; // 시작 시간은 그대로..
      times[i].end_time = arrival[i] + duration[i]; // 당연히 종료 시간 = 시작 시간 + 지속 시간이다.
   }

   /*
      times 벡터를 정렬한다. 정렬 기준은 compare 함수이다.
      종료 시간(end_time) 순으로 정렬하되, 종료 시간(end_time)이 같은 경우엔 시작 시간(start_time)이 빠른 놈으로 한다. 
         근데 사실 시작 시간 순으로 sort안해도 된다. 시작 시간은 아무렇게나해도 됨. 잘 생각해보면됨
   */
   sort(times.begin(), times.end(), compare);

   int last_finished_time = 0; // 마지막 회의 종료 시간 (시작 전에는 time = 0. 모든 start_time은 1 이상이니까 처음엔 0으로 두면 됨)
   int result = 0; // 선택한 회의 갯수. (시작 전에는 당연히 0개)
   for (int i=0; i<n; i++) { // 정렬된 회의들을 순서대로 sweeping하면서(훑으면서)

      // 마지막 회의 종료 시간이 i번째 회의의 시작시간(start_time) 이하인 경우 (즉, 회의실이 비어서 현재 회의가 들어갈 수 있는 경우)
      if (last_finished_time <= times[i].start_time) { 
         last_finished_time = times[i].end_time; // last_finished_time을 i번째 회의의 종료시간(end_time)으로 갱신해버린다. (즉, 회의를 추가해서 시작하고 끝났음)
         ++result; // i번째 회의를 선택했으므로 result에 +1
      }
   }
   return result; // 결과값 result를 리턴
}

int main()
{
   // 입력하는 부분 생략하고, 바로 변수에 저장
   int n = 3; // arrival[] size n = 3
   vector<int> arrival = { 1, 3, 5 }; // arrival = [1, 3, 5]
   vector<int> duration = { 2, 2, 2 }; // duration = [2, 2, 2]
   
   // maxEvents 함수 호출하고 결과값 저장
   int answer = maxEvents(arrival, duration);
   
   // 결과값 출력
   cout << answer;

   return 0; //정상 종료됨을 의미하는 return 0
}

 

주석 제거용

#include <bits/stdc++.h>
using namespace std; 

struct Time {
   int start_time;
   int end_time;
};

bool compare(Time t1, Time t2) { 
   if (t1.end_time == t2.end_time) {
      return t1.start_time < t2.start_time; 
   }
   return t1.end_time < t2.end_time;
} //끝나는 시간을 기준으로 정렬하기 위해 compare 함수를 만들었습니다. 

int maxEvents(vector<int> arrival, vector<int> duration) {
   int n = arrival.size();

   vector<Time> times(n);
   for (int i=0; i<n; i++) { 
      times[i].start_time = arrival[i];
      times[i].end_time = arrival[i] + duration[i]; 
   }

   sort(times.begin(), times.end(), compare);

   int last_finished_time = 0; 
   int result = 0; 
   for (int i=0; i<n; i++) {

      if (last_finished_time <= times[i].start_time) { 
         last_finished_time = times[i].end_time; 
         ++result; 
      }
   }
   return result;
}

int main()
{
   int n = 3; 
   vector<int> arrival = { 1, 3, 5 }; 
   vector<int> duration = { 2, 2, 2 }; 
   
   int answer = maxEvents(arrival, duration);
   
   cout << answer;

   return 0; 
}

'알고리즘' 카테고리의 다른 글

[2021 ICT 하반기] 5번 문제  (0) 2021.07.16
[2021 ICT 하반기] 3번 문제  (0) 2021.07.15
[2021 ICT 하반기] 2번 문제  (0) 2021.07.15
[2021 ICT 하반기] 1번 문제  (0) 2021.07.15

+ Recent posts