贪心算法

1、活动安排问题: 设有n个活动E={1,2,...,n},其中每个活动都要求使用同一资源(如演讲会场等),且在同一时间内只有一个活动能使用这一资源。如果选择了执行活动i,则它在半开的时间区间[s[i],f[i])内占用资源,其中s[i]<f[i],s[i]为其起始时间,f[i]为其结束时间。若区间[s[i],f[i])与[s[j],f[j])不相交,即s[i]>=f[j]或s[j]>=f[i],则称活动i与活动j是相容的。活动安排问题就是要在所给的活动集合中选出最大的相容活动子集A。
  用贪心算法求解:
  (1)贪心选择性质:即原问题的最优解可以通过一系列局部最优的选择(称为贪心选择)来达到。这种选择并不依赖于子问题的解,这是与动态规划算法的主要区别,动态规划算法求解时需要用到子问题的解。每次贪心选择都是作出当前状态下的最好选择,原问题就简化为一个规模更小的子问题。
  这里的贪心选择就是每次总是选择具有最早结束时间且相容的活动。设各活动1,2,..,n按结束时间的非减序f[1]<=f[2]<=...<=f[n]排列,如果给出的活动未按此序排列,我们可以用O(nlogn)的时间将它重排。贪心选择从活动1开始,我们需要证明存在一个以贪心选择开始的最优解,并且每作一次贪心选择就将原问题简化为更小的子问题。基本思路是先考察一个全局最优解,然后证明可修改这个最优解,使其以贪心选择开始,选择后将原问题化一个更小的子问题。
  设A是原问题的一个最优解,且A中的活动也按结束时间非减序排列,第一个活动是k。若k=1,则A就是以贪心选择开始的最优解。若k>1,设B=A-{k}并{1}。由于f[1]<=f[k],且A中活动互为相容,故B中活动也互为相容。又因|B|=|A|且A是最优解,故B也是最优解,且B以贪心选择活动1开始。
  (2)最优子结构性质:即原问题的最优解包含了作出贪心选择后的子问题的最优解。设B是包含活动1的一个原问题最优解,则B的子集C=B-{1}是子问题F={i属于E,且s[i]>=f[1]}的一个最优解。若不然,设D是子问题F的一个最优解,而C不是,则|D|>|C|,D中所有的活动与1相容。由于1不属于F,因此也不属于D。D并{1}是相容活动构成的集合,且元素个数大于B,这与B是原问题的最优解矛盾。
  算法如下:

[cpp]  view plain   copy
  1. //f中的元素按非减序排列f[1]<=f[2]<=...<=f[n]  
  2. template<class Type>  
  3. void GreedySelector(int n,Type s[],Type f[],bool A[]){  
  4.     A[1]=true//选择活动1  
  5.     int j=1;  //j表示上一次选择的活动  
  6.     for(int i=2;i<=n;i++)  //往后扫描所有的活动  
  7.         if(s[i]>=f[j]){ //若当前活动i和已选择的所有活动都相容(因为s[i]>=f[j]>=f[j-1]>=...>=f[1])  
  8.             A[i]=true;  //则选择该活动,将它加入到集合A中  
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值