贪心算法活动选择问题介绍与理解(含c源代码)

来源:互联网 发布:王者荣耀数据看不懂 编辑:程序博客网 时间:2024/05/17 21:26

贪心算法的活动选择问题:

  设有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相容。简单直白一点,就是让活动的区间更大,从而举办的活动更丰富多彩;如果c[i,j]表示集合si的最优解大小,递归式子为:

       c[i,j]=c[i,k]+c[k,j]+1;

最优解:

     c[i,j]=            0;    条件Sij为空集;

                           Max{  c[i,k]+c[k,j]+1  } ;条件Sij不为空集;

  贪心选择:

   对于活动选择问题,什么是贪心选择?直观上,就是我们应该选择一个活动,选出它后剩下的资源应能被尽量多的其他任务所用。现在考虑可选的活动,其中必然有一个最先结束。因此,直觉告诉我们,应该选择s中最早结束的活动,从而可以腾出更多时间活动;贪心算法通过求局部最优解获得全局最优解,贪心算法并不总能求得问题的整体最优解。但对于活动安排问题,贪心算法却总能求得的整体最优解,即它最终所确定的相容活动集合A的规模最大。这个结论可以用数学归纳法证明。

   例:设待安排的11个活动的开始时间和结束时间按结束时间的非减序排列如下:

 算法greedySelector 的计算过程如下图所示。图中每行相应于算法的一次迭代。阴影长条表示的活动是已选入集合A的活动,而空白长条表示的活动是当前正在检查相容性的活动。


C源代码(活动问题):

#include<stdio.h>#define MAX  12int s[MAX]={0,1,3,0,5,3,5,6,8,8,2,12};int f[MAX]={0,4,5,6,7,9,9,10,11,12,14,16};int GREEDY_ACTIVITY_SELECTOR(int *s,int *f);int main(){printf("整个活动的安排区间如下:\n");for(int i=1;i<=MAX-1;i++){printf("a%d",i);printf("区间为=(%d,%d);\n",s[i],f[i]); }printf("活动的最优安排:\n");GREEDY_ACTIVITY_SELECTOR(s,f);return 0;}int GREEDY_ACTIVITY_SELECTOR(int *s,int *f){int a=1;printf("a%d",a);printf("区间为=(%d,%d);\n",s[a],f[a]); int k=1;for(int m=2;m<=MAX;m++)  {  if(s[m]>=f[k])   {   a=m;   k=m;   printf("a%d",m);//首尾相接的原理; 区间的首尾相接;printf("区间为=(%d,%d);\n",s[m],f[m]);      } }}//迭代贪心算法;上面的a1=(1,4);a2=(3,5);a3=(0,6);a4=(5,7);a5=(3,9);a6=(5,9);//a7=(6,10);a8=(8,11);a9=(8,12);a10=(2,14);a11=(12,16);


 贪心算法的总结:

 时间复杂度为O(n);贪心算法对于活动的安排,从局部最优到达全局最优是可以实现的;活动按照单调递增的顺序排好序,这个解可以证明为最优解;后面将会介绍背包问题以及赫夫曼编码问题将会更加有趣,并且这些问题用贪心算法能够解决和达到最优解吗?一起共同学习与进步!


0 0