1. 程式人生 > >貪心演算法區間圖著色問題

貪心演算法區間圖著色問題

問題來自演算法導論十六章,使用盡可能少的教室對一系列活動進行排程。
思路,把能相容的活動放在以一個教室。
先把所有活動按結束時間遞增的順序排列,方便以後的迴圈。選取快速排序,期望時間複雜度為nlgn,最壞為n^2.快排我都有點忘記了,但是看了一下演算法導論的圖就秒懂了,可見學演算法結合圖形還是很重要的事情。
迴圈活動,把每個活動往教室裡填,看活動是否與教室裡已有的活動相容(也就是開始時間是否比最後一個活動的結束時間更晚),如果相容,就填進教室裡去,如果不相容,就新開一個教室存放該活動。繼續迴圈。

程式碼如下,註釋很詳細。參考了一位博主的程式碼,現在找不到他那個頁面了,見諒…該博主用了結構體,這個問題確實很適合用結構體,在一個活動中有開始時間結束時間然後表狀態,記錄選擇。不用去定義很多陣列再一一對應。學習學習



#include "stdafx.h"
#include<stdio.h>
# define N 100

struct Activity
{
	int number;            //活動編號
	int begin;           //活動開始時間
	int end;            //活動結束時間
	bool flag;          //此活動是否被選擇
	int roomnum;      //此活動在哪間教室舉行
};


//對於活動集,按照結束時間遞增排序,使用快速排序
void quicksort(Activity *a, int p, int r)
{
	if
(p < r) { int i = p- 1,j=p; Activity aa = a[r]; while (j < r) //這個while迴圈是在將陣列劃分為小於最後一個元素,大於最後一個元素和最後一個元素三部分。 { if (a[j].end <= aa.end) { i++; //i總是指向第一個區域的最後一個元素,然後i++去佔領新的位置。j始終指向第二個區域的最後一個元素的下一個元素,也就是即將歸類的新元素
Activity t = a[i]; a[i] = a[j]; a[j] = t; } j++; } Activity t = a[r]; //以下三行的交換是為了把最後一個元素提到他應該有的位置 a[r] = a[i + 1]; a[i + 1] = t; quicksort(a, p, i); quicksort(a, i + 1, r); } } int select_room(Activity *a, int *time, int n) { int i = 1, j = 1; //下面初始化資料,把第一個活動安排了,然後迴圈從第二個活動開始 int sumroom=1; //已經佔用的教室,計算然後返回最終值 int sumact=1; //已經被選擇的活動,初始化為1 time[1] = a[0].end; //初始化教室1的最後一個活動的結束時間為活動1的結束時間 a[0].roomnum = 1; //將第一個活動佔用的教室初始化為教室1 for (i = 1; i < n; i++) //遍歷i個活動 { for(j=1;j<=sumroom;j++) //遍歷j個教室,把活動i放進哪個教室 if (a[i].begin >= time[j] && (!a[i].flag)) //活動i開始的時間比教室j最後一個活動的結束時間晚,且活動i沒有被規劃過。那麼就應該吧活動i劃入教室j { //進行一波更新 a[i].roomnum = j; a[i].flag = true; time[j] = a[i].end; sumact++; } if (sumact < n&&i == n - 1) //已經把一間教室能加入的活動搞完了,活動i不能已有加入教室,那麼它就自己新開一間教室 { i = 0; //控制重新遍歷的條件 sumroom++; } } return sumroom; } int main() { Activity a[N]; //定義一個結構體 int time[N]; //time 用於記錄某個教室裡面末尾活動的結束時間,方便與下一個活動的開始時間比較 int n,i=0,j; //輸入的活動個數 int sum; int k = 0; printf("輸入活動個數:\n"); scanf_s("%d", &n); for (i = 0; i < n; i++) { time[i + 1] = 0; a[i].number = i + 1; a[i].flag = false; a[i].roomnum = 0; printf("輸入活動%d的開始時間:", ++k); scanf_s("%d", &a[i].begin); printf("輸入活動%d的結束時間:", k); scanf_s("%d", &a[i].end); } quicksort(a, 0, n - 1); sum = select_room(a, time, n); printf("所佔教室總數目是:%d\n", sum); for (i = 0; i < n; i++) printf("活動%d在教室%d中\n", a[i].number, a[i].roomnum); }