【贪心法】--活动安排问题

【贪心法】--活动安排问题

1、活动安排

  设有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 相容。

  活动安排问题就是在所给的活动集合中选出最大的相容活动子集合。

 例如:

2、算法分析

【时间复杂度&&优化】  

  该算法只用一层循环,当结束时间f[i]数组按照非减序排列时,该算法的时间复杂度是O(n);

  若结束时间f[i]数组未排好序,则至少用O(nlogn)的时间进行重排;

【算法精髓】

   每次在循环(有且仅有1轮循环)中,用j进行更新,来标记哪个活动是可安排的,即b数组,从而避免了两层循环套循环的复杂度;

b数组中标记为1的活动,互相之间是可相容的。

【最优量度标准】

   即如何判断两个活动之间是可相容的,s[i]>=f[j] 若下一活动的开始时间晚于之前活动的结束时间,则这两个活动是相容的

相关链接1

相关链接2

【源代码】        
#include <iostream>
using namespace std;

const int N = 11;//活动的数量

void GreedySelector(int n, int s[], int 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;//标记该活动是不可安排的
        }
    }
}

int main()
{

    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};    //下标从1开始,存储活动结束时间
    bool b[N+1];//存储被安排的活动编号

    cout<<"各活动的开始时间,结束时间分别为:"<<endl;
    for(int i=1;i<=N;i++)
    {
        cout<<"["<<i<<"]:"<<"("<<s[i]<<","<<f[i]<<")"<<endl;
    }

    GreedySelector(N,s,f,b);

    cout<<"最大相容活动子集为:"<<endl;
    for(int i=1;i<=N;i++)
    {
        if(b[i]){
            cout<<"["<<i<<"]:"<<"("<<s[i]<<","<<f[i]<<")"<<endl;
        }
    }

    return 0;
}



        




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值