【算法分析】实验 1. 基于贪心的会议安排问题
目錄實驗內容實驗目的環境要求實驗結果步驟一步驟二步驟三步驟四步驟五步驟六實驗總結附錄:測試數據
實驗內容
本實驗要求基于算法設計與分析的一般過程(即待求解問題的描述、算法設計、算法
描述、算法正確性證明、算法分析、算法實現與測試),針對會議安排算法從實踐中理解貪
心法的思想、求解策略及步驟。
實驗目的
理解貪心法的核心思想以及貪心法的求解過程
從算法分析與設計角度,對貪心算法有更進一步的理解
環境要求
算法實現可以選擇C,java,python,C++等任意的程序設計語言
實驗結果
步驟一
理解問題,給出問題的描述:
有n個會議集合 A={1,2,3...n},這些會議都使用的是同一個會議室且在同一時間內最多只有一個會議可以使用該會議室,所以需要根據所有會議舉辦的時間進行協商。目標是盡可能選擇更多的會議來使用資源。
給出每一個會議所占用的時間段,表示形式為 $[b_i , e_i) $ , 其中(b_i , e_i)是int型的整數來代表時間。
步驟二
算法設計,包括策略與數據結構的選擇,目前可以選擇的貪心策略有:
選擇最早開始時間且不與已安排會議重疊的會議
選擇使用時間最短且不與已安排會議重疊的會議
選擇最早結束時間且不與已安排會議重疊的會議
三個貪心策略中應該選擇第三個,因為在這道題的情景之下,貪心的對象應該轉化為使剩余時間的可安排時間段盡可能大,以便之后的會議能夠有更多的時間來進行。
步驟三
描述算法,用偽代碼的方式來描述算法
//A存儲的是成對信息 A[i]代表的是第i個會議
//有兩個屬性,begin開始時間,end結束時間
//num代表的是一共有多少個會議
ARRANGE_MEETING(A,num)
SORT_ASC(A) //根據end結束時間進行降序排序,如果end相同,則根據begin來進行排序
NOW_END = A[0].end //選擇第一個會議
CNT=1 //記錄選擇了幾個會議
for i = 1 to num:
if A[i].begin >= NOW_END:
NOW_END = A[i].end
CNT++
return CNT;
步驟四
算法的正確性證明
從兩個角度對該貪心法進行正確性分析:
最優子結構性質證明
通過反證法進行證明,將原問題轉化為:
假設B'不是會場安排問題的最優解,那么(|A_1| > |A’|)。
貪心選擇會議1后,原問題簡化為對C中所有與會議1相容的會議進行安排的子問題。即若A是原問題的一個最優解,則(A')=A-{1}一定是會議安排問題(C_i)={i∈C|(b_i) ≥ (e_i)}的一個最優解。利用反證法,假設(A')不是會場安排問題(C_1)的一個最優解,則 |(A_1)|>|(A')|。令(A_2=A_1))∪{1},由于(A_1)中的會議開始時間均大于等于(e_1),因此(A_2)是問題C的一個解。因為|(A_2)=(A_1){1}|>|(A')∪{1} = A|,所以A不是問題的最優解,與原題設產生矛盾。
貪心選擇性質證明
設C={1,2,…,n}是所給的會議集合,且按結束時間非減序排列。設(C^*) 是所給問題的一個最優解,且(C^*) 中會議結束時間也按結束時間進行非減序排序(C^*) 中的第一個會議是會議 k,如果 k = 1,則就是(C^*) 一個以貪心選擇的最優解。如果 k > 1,則設(C’=C^*-{k}∪{1})。由于(e_1 <= e_K),且$C^* (-{k}中任何一個會議都互為相容會議,它們的開始時間都大于等于)e_k(,所以)C^* (-{k}的開始時間大于等于)e_1(,所以C'中的會議也互為相容會議。因此)|C'| = |C^*|$, (C^*)也是最優的。(C')是一個以貪心算法選擇活動1開始的最優會議安排。
步驟五
算法復雜性分析,包括時間復雜度和空間復雜度。
時間復雜度
時間復雜度由兩部分構成,分別是排序所需要的時間以及遍歷一遍所需要的時間。
排序的復雜度跟采用的算法有關,如果采用冒泡排序,那么復雜度為(O(n^2));如果采用的是快速排序,那么排序部分復雜度為(O(nlog(n)))。
遍歷一遍所用的時間為(O(n))。
因為這里直接用的是STL中的快速排序,所以總體的時間復雜度為:(O(nlog(n))) 。
空間復雜度
空間只用了一個變量,所以空間復雜度為(O(1)) 。
步驟六
算法的實現與測試,貼上算法運行結果圖。
代碼:C++版本
#include <bits/stdc++.h>
const int maxn = 1000;
using namespace std;
int num;
struct meeting
{
int b_time;
int e_time;
meeting()
{
b_time = 0;
e_time = 0;
}
};
meeting m[maxn];
queue<meeting> record;
bool cmp(meeting m1, meeting m2)
{
if(m1.e_time == m2.e_time)
return m1.b_time < m2.b_time;
else
return m1.e_time < m2.e_time;
}
int main()
{
cout << "Input the number of the meeting:";
cin >> num;
for(int i = 0 ; i < num; i++){
cin >> m[i].b_time >> m[i].e_time;
}
sort(m,m+num,cmp);
for(int i = 0 ; i < num ; i++){
cout << m[i].b_time << "," << m[i].e_time << endl;
}
int now_e_time = m[0].e_time;
int cnt = 1;
record.push(m[0]);
for(int i = 1 ; i < num ; i++)
{
if(m[i].b_time > now_e_time)
{
now_e_time = m[i].e_time;
cnt++;
record.push(m[i]);
}
}
cout << "Max number of the meeting:" << cnt << endl;
while(!record.empty())
{
meeting head = record.front();
record.pop();
cout << head.b_time << "," << head.e_time << endl;
}
return 0;
}
運行結果:
代碼:(Python3.6版本)
# -*- coding: utf-8 -*-
"""
Created on Tue Sep 18 17:26:16 2018
@author: pprp
"""
sav = []
def answer(meetings):
last_end = -1
ans = 0
for end,start in sorted((end,start) for start,end in meetings ):
if start >= last_end:
last_end = end
ans += 1
sav.append([start,end])
print("最佳安排會議個數為: %s" % ans)
print("以下為被安排的會議:")
for a in sav:
print(a)
meetings = [(2,3),(1,5),(4,6),(5,7),(6,9),(9,11)]
answer(meetings)
運行結果:
runfile('C:/Users/pprp/Desktop/Greedy.py', wdir='C:/Users/pprp/Desktop')
最佳安排會議個數為: 4
以下為被安排的會議:
[2, 3]
[4, 6]
[6, 9]
[9, 11]
實驗總結
心得體會與備忘
本次實驗是最基礎的算法-貪心算法。貪心算法是在對問題求解的時候,總是選取目前情況下的最優選擇,而不從整體上加以考慮,做出的決定是局部最優解。雖然貪心算法有時候無法得到整體最優解,但是通常得到的解是比較接近最優解的。貪心算法是采用了自頂向下的思想,將問題規模逐漸縮小,其可以解決的問題通常有兩個性質:最優子結構和貪心選擇性質。
最優子結構的證明通常需要反證法,需要構造一個原問題和子問題組成的條件。通過假設子問題不是最優解,另外再找一個作為最優解,然后進行反推到原問題,發現矛盾,最終得證。
貪心選擇性質的證明需要將問題轉化,如果不按照這種策略進行走下去,那么得到的內容就不可能是最優的。如果按照這種策略走下去,那么得到的下一步也一定是最優的解。
與動態規劃的關系:
動態規劃子結構很多問題重復,貪心算法子問題互相獨立。
貪心算法依賴當前已經做出的選擇。
兩者思路都是自頂向下。
動態規劃需要將全部子問題解決才能得到結果。
貪心算法只要解決一個子問題。
更為詳細的對比:來源:https://www.cnblogs.com/batys/p/3322553.html
| 標準分治 | 動態規劃 | 貪心算法 | |
|---|---|---|---|
| 適用類型 | 通用問題 | 優化問題 | 優化問題 |
| 子問題結構 | 每個子問題不同 | 很多子問題重復(不獨立) | 只有一個子問題 |
| 最優子結構 | 不需要 | 必須滿足 | 必須滿足 |
| 子問題數 | 全部子問題都要解決 | 全部子問題都要解決 | 只要解決一個子問題 |
| 子問題在最優解里 | 全部 | 部分 | 部分 |
| 選擇與求解次序 | 先選擇后解決子問題 | 先解決子問題后選擇 | 先選擇后解決子問題 |
附錄:測試數據
輸入數據:
7
1 5
2 3
4 6
5 7
7 8
6 9
9 11
排序后數據:
2,3
1,5
4,6
5,7
7,8
6,9
9,11
最佳安排會議的個數:
4
總結
以上是生活随笔為你收集整理的【算法分析】实验 1. 基于贪心的会议安排问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何处理SAP Fiori Launch
- 下一篇: Twitter变Titter!马斯克将旧