活动安排问题 之 贪心算法

贪心算法思想:  顾名思义,贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。当然,希望贪心算法得到的最终结果也是整体最优的。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。如单源最短路经问题,最小生成树问题等。在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。

 

活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合,是可以用贪心算法有效求解的很好例子。该问题要求高效地安排一系列争用某一公共资源的活动。贪心算法提供了一个简单、漂亮的方法使得尽可能多的活动能兼容地使用公共资源。

 

问题表述:设有n个活动的集合E={1,2,,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,si<fi。如果选择了活动i,则它在半开时间区间[si, fi)内占用资源。若区间[si, fi)与区间[sj, fj)不相交,则称活动i与活动j是相容的。也就是说,当si≥fjsj≥fi时,活动i与活动j相容。

      由于输入的活动以其完成时间的非减序排列,所以算法greedySelector每次总是选择具有最早完成时间的相容活动加入集合A中。直观上,按这种方法选择相容活动为未安排活动留下尽可能多的时间。也就是说,该算法的贪心选择的意义是使剩余的可安排时间段极大化,以便安排尽可能多的相容活动。

算法greedySelector的效率极高。当输入的活动已按结束时间的非减序排列,算法只需O(n)的时间安排n个活动,使最多的活动能相容地使用公共资源。如果所给出的活动未按非减序排列,可以用O(nlogn)的时间重排。

贪心算法并不总能求得问题的整体最优解。但对于活动安排问题,贪心算法却总能求得的整体最优解,即它最终所确定的相容活动集合A的规模最大。这个结论可以用数学归纳法证明。

#include <stdio.h>
#include <stdlib.h>
#include <mem.h>  
typedef struct activity  
{  
    int start;  
    int finish;  
}activity;  
  //选择排序 
void sort(activity *a,int n)  
{  
    activity t;
	int min,i,j;  
    for( i=0;i<n;i++)  
    {  
        min = i; 
        for( j=i+1;j<n;j++)  
        {  
            if(a[j].finish < a[min].finish) min = j;  
        } 
		if(min != i){
			t = a[i];
			a[i] = a[min];
			a[min] = t;
		} 
    }  
}  
int main()  
{  
    int n,i;  
	printf("请输入要安排的活动的个数:");
	scanf("%d",&n);
	
    activity *a = (activity *)malloc(sizeof(activity)*n);  
    printf("请输入各个活动的开始时间和结束时间: ");
    for( i=0;i<n;i++){
    	scanf("%d %d",&a[i].start,&a[i].finish);
	}  
       
    sort(a,n); 
	 for(i =0 ;i<n;i++)
	 {
	 	printf("<%d,%d>\n",a[i].start,a[i].finish);
	 }
	 
    int * t =(int *)malloc(sizeof(int)*n);  
    memset(t,0,sizeof(int)*n);  
    
    t[0]=1;  
    int j=0;  
    for(i=1;i<n;i++)  
    {  
        if(a[i].start < a[j].finish )
			continue;  
        else {j = i; t[j]=1;}  
    }  
    
    for(i=0;i<n;i++)  
    {  
       if(t[i] ==1){
       	printf("<%d,%d>\n",a[i].start,a[i].finish);
	   } 
    }
	free(a);
	free(t);  
    return 0;  
}  

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值