1. 程式人生 > >C++會場安排問題(貪心演算法)

C++會場安排問題(貪心演算法)

一、問題描述

問題描述:假設要在足夠多的會場裡安排一批活動,並希望使用盡可能少的會場。

★演算法設計:對於給定的k個待安排的活動,計算使用最少會場的時間表。

★資料輸入:第一行有1個正整數k,表示有k個待安排的活動。接下來的k行中,每行有兩個正整數,分別表示k個待安排的活動開始時間和活動結束時間。時間以0點開始的分鐘計。

★結果輸出:將計算結果輸出到檔案output.txt。檔案第1行中的數是計算出的最大值。

輸入檔案示例:input.txt

5

1 23

12 28

25 35

27 80

36 50

輸出檔案示例:output.txt

3

二、問題分析

1.輸入資料的儲存和表示:

首先需要定義一個結構體來表示活動,其中包括活動的開始時間和結束時間。

其次需要定義一個整形變數來表示會場的空閒時間,或者說是該會場最後一個活動的結束時間。

2.解題思路

這個問題是書本上4.1活動安排問題的變形。

1.書本例題4.1的思路。

4.1活動安排問題說的是如何在一個會場中安排下足夠多的活動。它通過先將所有的活動按結束時間從小到大進行排序,再將依次選擇那些沒有時間衝突的的活動。一開始先選擇活動1,如何依次檢查活動i是否與當前所有活動相容(只要和最後一個相容即可)。若相容則將活動i加入到已選擇的活動中,否則不選擇活動i,而繼續檢查下一活動與當前活動的相容性。通過比較待檢查活動的開始時間與當前所有活動的結束時間來判斷相容性。如果待檢查的活動開始時間大於所有當期活動的結束時間,則是相容的。直觀上,這種方法選擇相容活動為未安排活動留下儘可能多的時間。貪心選擇的意義是使剩餘可安排時間段極大化。

數學證明該種貪心演算法總是能取得最優解:

設集合A為最優解集合,其中第一個集合為k。如果k=1,則說明該集合是貪心選擇得出的最優解。如果k>1,令集合B=(A-{k})U{1}。因為活動1的結束時間比活動k少,並且集合A是相容的,所以集合B也是相容。兩個集合的活動個數也是一樣多的。因此集合A也是該問題的最優解之一。

2.本題的思路

本題要實現用最少的會場來安排完所有的活動。也就是每個會場的利用率要達到最大。

首先,先申請一個會場,用roomavail來記錄該會場的空閒時間段,也就是最後一個活動的結束時間。先遍歷所有的活動,通過貪心演算法來記錄可以安排哪些活動,將已安排好的活動記為ok=1,未安排的為

ok=0。遍歷結束後重新申請一個新會場,即將roomavail重新初始化為0並使roomnum+1表明當前使用的會場數增加1。當所有的活動都被安排好以後退出迴圈。

三、詳細設計(從演算法到程式)

#include<iostream>
#include<fstream>
#include<sstream>
using namespace std;

struct Job{
	int begin,end;
	bool ok;
};

int manage(int n,Job *b){
	int count=n,roomavail=0,roomnum=0;//count表示還剩餘幾個活動未安排
	while(count>0){//當count=0就退出while迴圈
		for(int i=1;i<=n;i++){
			if((b[i].begin>roomavail)&&(b[i].ok==0)){//如果當前活動未安排並且和會場中已   //有活動不衝突
				roomavail=b[i].end;//將當前活動加入該會場,並且更新會場的空閒時間
				b[i].ok=1;//標記該活動已被安排
				count--;//未安排的活動數減1
			}
		}
		roomavail=0;//把roomavail初始化,相當於重新再找一個房間 
		roomnum++;//遍歷一次,使用的會場數加1
	}
	return roomnum;//返回使用的會場數
}

int main(){
	ifstream cinfile;
	cinfile.open("input.txt",ios::in);
	int n,roomnum;
	cinfile>>n;
	Job b[n+1];
	b[0].begin=0;b[0].end=0;b[0].ok=0;
	for(int i=1;i<=n;i++){
		cinfile>>b[i].begin>>b[i].end;
		b[i].ok=0;
	}
	cinfile.close();
	
    for(int i=1;i<=n;i++){//排序
		for(int j=i+1;j<=n;j++){
			if(b[i].end>b[j].end){
				Job Register=b[i];
				b[i]=b[j];
				b[j]=Register;
			}
		}
	}
	roomnum=manage(n,b);
	
	ofstream outfile;
	outfile.open("output.txt",ios::out);
	outfile<<roomnum<<endl;
	outfile.close();
	return 0;
}
/*
5
1 23
12 28
25 35
27 80
36 50
*/

四、程式執行結果

 

五、分析與總結

(1).解問題時要將問題分解為一些較為容易和常見的子問題。

(2).在使用貪心演算法解決問題時,首先要證明該問題是否具有貪心選擇性質。

(3).當某個物件具有多個性質時,可以考慮使用結構體。