問題:
假設要在足夠多的會場里安排一批活動,並希望使用盡可能少的會場。
(這個問題實際上是著名的圖着色問題。若將每一個活動作為圖的一個頂點,不相容活動間用邊相連。使相鄰頂點有不同顏色的最小着色數,相應於要找的最小會場數。)
數據輸入:
第一行表示有 n 個活動。
接下來 n 行中,第 i 行的第一個數表示該活動的開始時間,第二個數表示該活動的結束時間。
數據輸入:
輸出最少需要的會場數。
思路:
將n個活動1,2,....,n看做實直線上的n個半閉活動區間(s[i],f[i]])。
所討論的問題實際上是求這n個半閉區間的最大重疊數。
因為重疊的活動區間所相應的活動是互不相容的。若這n個活動區間的最大重疊數為m,則這m個重疊區間所對應的活動互不相容,因此至少要安排m個會場來容納這m個活動。
如圖:
將所有的時刻(開始的,結束的)按順序排在一條線上,然后從這條線的開頭往后面走,遇到的時刻是開始的話,重疊數就+1,遇到的時刻是結束的話,重疊數就-1.
代碼:
#include<iostream> #include<fstream> using namespace std; struct activity { int time; //記錄一個時刻 bool f; //表示這個是開始時刻還是結束時刻 }; void quickSort(activity s[], int l, int r) {//快速排序函數,這個不是重點 if (l < r) { int i = l, j = r; activity x = s[l]; while (i < j) { while (i < j && s[j].time >= x.time) j--; if (i < j) s[i++] = s[j]; while (i < j && s[i].time < x.time) i++; if (i < j) s[j--] = s[i]; } s[i] = x; quickSort(s, l, i - 1); quickSort(s, i + 1, r); } } int activityPlan(activity a[], int l) {//會場安排函數 int overlap = 0, halls = 0; //overlap 表示重疊數,halls表示需要的最少的會場數 for (int i = 1; i <= l; i++) { if (a[i].f == true) {//遇到開始時間 overlap++; if (overlap > halls) {//會場數即最大的重疊數 halls = overlap; } } else {//遇到結束時間 overlap--; } } return halls; } void main() { ifstream input("input.txt"); ofstream output("output.txt"); int n, t; activity a[99]; input >> n; //輸入 for (int i = 1; i <= 2 * n; i++) { input >> a[i].time; if (i % 2 == 1) a[i].f = true; else a[i].f = false; } //先對輸入的所有時刻進行排序 quickSort(a, 1, 2 * n); output << activityPlan(a, 2 * n) << endl; input.close(); output.close(); }