程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 貪心算法與活動安排問題

貪心算法與活動安排問題

編輯:C++入門知識

     1、貪心算法      (1)原理:在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,他所做出的僅是在某種意義上的局部最優解。貪心算法不是對所有問題都能得到整體最優解,但對范圍相當廣泛的許多問題他能產生整體最優解或者是整體最優解的近似解。       (2)特性:貪心算法采用自頂向下,以迭代的方法做出相繼的貪心選擇,每做一次貪心選擇就將所求問題簡化為一個規模更小的子問題,通過每一步貪心選擇,可得到問題的一個最優解,雖然每一步上都要保證能獲得局部最優解,但由此產生的全局解有時不一定是最優的,所以貪婪法不要回溯。能夠用貪心算法求解的問題一般具有兩個重要特性:貪心選擇性質和最優子結構性質。      1)貪心選擇性質      所謂貪心選擇性質是指所求問題的整體最優解可以通過一系列局部最優的選擇,即貪心選擇來達到。這是貪心算法可行的第一個基本要素。貪心算法則通常以自頂向下的方式進行,以迭代的方式作出相繼的貪心選擇,每作一次貪心選擇就將所求問題簡化為規模更小的子問題。      對於一個具體問題,要確定它是否具有貪心選擇性質,必須證明每一步所作的貪心選擇最終導致問題的整體最優解。證明的大致過程為:首先考察問題的一個整體最優解,並證明可修改這個最優解,使其以貪心選擇開始。做了貪心選擇後,原問題簡化為規模更小的類似子問題。然後用數學歸納法證明通過每一步做貪心選擇,最終可得到問題的整體最優解。其中,證明貪心選擇後的問題簡化為規模更小的類似子問題的關鍵在於利用該問題的最優子結構性質。      2)最優子結構性質       當一個問題的最優解包含其子問題的最優解時,稱此問題具有最優子結構性質。      (3)貪心算法與動態規劃算法的差異:      動態規劃和貪心算法都是一種遞推算法,均有最優子結構性質,通過局部最優解來推導全局最優解。兩者之間的區別在於:貪心算法中作出的每步貪心決策都無法改變,因為貪心策略是由上一步的最優解推導下一步的最優解,而上一部之前的最優解則不作保留,貪心算法每一步的最優解一定包含上一步的最優解。動態規劃算法中全局最優解中一定包含某個局部最優解,但不一定包含前一個局部最優解,因此需要記錄之前的所有最優解。       (4)基本思路:      1)建立數學模型來描述問題。      2)把求解的問題分成若干個子問題。      3)對每一子問題求解,得到子問題的局部最優解。      4)把子問題的解局部最優解合成原來解問題的一個解。      2、活動安排問題      活動安排問題就是要在所給的活動集合中選出最大的相容活動子集合,是可以用貪心算法有效求解的很好例子。該問題要求高效地安排一系列爭用某一公共資源的活動。貪心算法提供了一個簡單、漂亮的方法使得盡可能多的活動能兼容地使用公共資源。      問題描述:      設有n個活動的集合E={1,2,…,n},其中每個活動都要求使用同一資源,如演講會場等,而在同一時間內只有一個活動能使用這一資源。每個活動i都有一個要求使用該資源的起始時間si和一個結束時間fi,且si <fi。如果選擇了活動i,則它在半開時間區間[si, fi)內占用資源。若區間[si, fi)與區間[sj, fj)不相交,則稱活動i與活動j是相容的。也就是說,當si≥fj或sj≥fi時,活動i與活動j相容。活動安排問題就是要在所給的活動集合中選出最大的相容活動子集合。       求解思路:      將活動按照結束時間進行從小到大排序。然後用i代表第i個活動,s[i]代表第i個活動開始時間,f[i]代表第i個活動的結束時間。按照從小到大排序,挑選出結束時間盡量早的活動,並且滿足後一個活動的起始時間晚於前一個活動的結束時間,全部找出這些活動就是最大的相容活動子集合。事實上系統一次檢查活動i是否與當前已選擇的所有活動相容。若相容活動i加入已選擇活動的集合中,否則,不選擇活動i,而繼續下一活動與集合A中活動的相容性。若活動i與之相容,則i成為最近加入集合A的活動,並取代活動j的位置。      下面給出求解活動安排問題的貪心算法,各活動的起始時間和結束時間存儲於數組s和f中,且按結束時間的非減序排列。如果所給的活動未按此序排列,可以用O(nlogn)的時間重排。具體代碼如下: [cpp]   //4d1 活動安排問題 貪心算法   #include "stdafx.h"   #include <iostream>    using namespace std;       template<class Type>   void GreedySelector(int n, Type s[], Type f[], bool A[]);      const int N = 11;      int main()   {       //下標從1開始,存儲活動開始時間       int s[] = {0,1,3,0,5,3,5,6,8,8,2,12};          //下標從1開始,存儲活動結束時間       int f[] = {0,4,5,6,7,8,9,10,11,12,13,14};          bool A[N+1];          cout<<"各活動的開始時間,結束時間分別為:"<<endl;       for(int i=1;i<=N;i++)       {           cout<<"["<<i<<"]:"<<"("<<s[i]<<","<<f[i]<<")"<<endl;       }       GreedySelector(N,s,f,A);       cout<<"最大相容活動子集為:"<<endl;       for(int i=1;i<=N;i++)       {           if(A[i]){               cout<<"["<<i<<"]:"<<"("<<s[i]<<","<<f[i]<<")"<<endl;           }       }          return 0;   }      template<class Type>   void GreedySelector(int n, Type s[], Type f[], bool A[])   {       A[1]=true;       int j=1;//記錄最近一次加入A中的活動          for (int i=2;i<=n;i++)//依次檢查活動i是否與當前已選擇的活動相容       {           if (s[i]>=f[j])           {                A[i]=true;               j=i;           }           else           {               A[i]=false;           }       }   }        由於輸入的活動以其完成時間的非減序排列,所以算法greedySelector每次總是選擇具有最早完成時間的相容活動加入集合A中。直觀上,按這種方法選擇相容活動為未安排活動留下盡可能多的時間。也就是說,該算法的貪心選擇的意義是使剩余的可安排時間段極大化,以便安排盡可能多的相容活動。算法greedySelector的效率極高。當輸入的活動已按結束時間的非減序排列,算法只需O(n)的時間安排n個活動,使最多的活動能相容地使用公共資源。如果所給出的活動未按非減序排列,可以用O(nlogn)的時間重排。       例:設待安排的11個活動的開始時間和結束時間按結束時間的非減序排列如下:          算法greedySelector 的計算過程如下圖所示。圖中每行相應於算法的一次迭代。陰影長條表示的活動是已選入集合A的活動,而空白長條表示的活動是當前正在檢查相容性的活動。            若被檢查的活動i的開始時間Si小於最近選擇的活動j的結束時間fi,則不選擇活動i,否則選擇活動i加入集合A中。貪心算法並不總能求得問題的整體最優解。但對於活動安排問題,貪心算法greedySelector卻總能求得的整體最優解,即它最終所確定的相容活動集合A的規模最大。這個結論可以用數學歸納法證明。      證明如下:設E={0,1,2,…,n-1}為所給的活動集合。由於E中活動安排安結束時間的非減序排列,所以活動0具有最早完成時間。首先證明活動安排問題有一個最優解以貪心選擇開始,即該最優解中包含活動0.設a是所給的活動安排問題的一個最優解,且a中活動也按結束時間非減序排列,a中的第一個活動是活動k。如k=0,則a就是一個以貪心選擇開始的最優解。若k>0,則我們設b=a-{k}∪{0}。由於end[0] ≤end[k],且a中活動是互為相容的,故b中的活動也是互為相容的。又由於b中的活動個數與a中活動個數相同,且a是最優的,故b也是最優的。也就是說b是一個以貪心選擇活動0開始的最優活動安排。因此,證明了總存在一個以貪心選擇開始的最優活動安排方案,也就是算法具有貪心選擇性質。      程序運行結果如下:     

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved