贪心算法之活动安排问题C++实现

问题描述

设有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相容。活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合。

题目分析

这道题我们可以使用我之间一直在更新的动态规划法进行求解,逐渐找出前一个时间段的最大活动数,观察该时间区间和上一个时间区间是相容。如果相容则可以更新为上一时间区间的最大活动书+1,否则未上一时间区间活动数。
但显然这不是最快的方法,最快的方法就是我们接下来要更新的下一主题——贪心算法。
贪心算法就是在每一步都找出当前最优解,也就是局部最优,最后拼接在一起就变成了全局最优。
就算最后的解不是全局最优解,也是一个近似全局最优的解。
通常我们都会按照活动结束时间的非递减序列给出这些活动的顺序。如果没有题目没有按照这种顺序,我们可以利用排序算法来达成,时间复杂度为O(nlogn)。
我们将活动的起始时间和结束时间分别存入s和f数组中,然后依次遍历s和f数组,如果后面的活动的起始时间>结束时间,那么这两个活动就是相容的,我们就可以用A数组储存结果,其中0代表这个活动不能加入,1代表这个活动可以加入。所以说只要两个活动相容我们就直接加入活动安排中,这样一定可以达到全局最优。

代码

#include <iostream>
using namespace std;
template<class Type>
void GreedySelector(int n,Type s[],Type f[],bool A[])
{
    int j = 1;
    A[1] = true;
    for(int i = 2;i <= n;i++)
    {
        if(s[i] > f[j])
        {
            A[i] = true;
            //将j更新为当前刚加入安排中的活动,也就是活动安排列表中的最后一个元素
            //下次需要和j比较,看下一活动与其是否相容
            j = i;
        }
        else
            A[i] = false;
    }
}

只遍历了一次,所以时间复杂度为O(n),如果一开始没排序就是O(nlogn)

总结

贪心算法的全局最优是需要证明,以后的几篇文章我会加入证明部分,这一篇就不进行证明了。证明的方法主要是数学归纳法和反证法。

发布了60 篇原创文章 · 获赞 2 · 访问量 1061

猜你喜欢

转载自blog.csdn.net/weixin_44755413/article/details/105532494