思考-贪心算法

基本要素:
贪心算法通过一系列的选择来得到问题的解。所做的每一个选择都是当前状态下局部最好的选择,即贪心选择。这种启发式策略的策略并不能总奏效,然而在很多情况下确实也能达到预期目的。
类似有一个竹筐:忽略空间,按质量装物体,上限100。竹筐最后的质量越接近100,得到的解最优,60及格。贪心算法首先拿到一个80的物体,会忽略后边连续的3个30的物体,从而最后是80的总重,而不是最好的90.


性质:
贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优选择,即贪心选择来达到.在贪心算法中,仅仅在当前状态下做出最好的选择,即局部最优选择。然后再去解出这个选择后产生的子问题。贪心算法所做的贪心选择可以依赖于以往所做过的选择,但绝不依赖于将来所做的选择,也不依赖于子问题的解。贪心算法通常自顶向下的方式进行,以迭代的方式做出相继的贪心选择,每做一次贪心选择就将所求问题简化为更小规模的子问题。
对于一个具体的问题,要确定它是否具有贪心选择性质,必须证明每一步所做的贪心选择最终导致问题的整体最优解。考察一个问题的整体最优解,并证明可修改这个最优解,使其以贪心选择开始。做了贪心选择后,原问题简化为规模更小的类似子问题。然后用数学归纳法证明,通过每一步做贪心选择,最终可得到问题的整体最优解。其中,证明贪心选择后的问题简化为规模更小的类似子问题的关键在于利用该问题的最优子结构性质。


最优子结构性质
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题是否可用贪心算法求解的关键特征。


例子:设有n个活动的集合E={1,2,3 n},其中每个活动都要求使用同一资源,如会场,广场等,而在同一时间内只有一个活动能使用这一资源。每个活动 i 都有一个要求使用该资源的起始时间 si 和一个结束时间 fi ,且 si < fi .如果选择了活动 i ,则它在半开时间区间[ si , fi )内占用资源。若区间[ si , fi )与区间[ sj , fj )不相交,则称活动 i 与活动 j 是相容的。也就是说,当 si fj sj fi 时,活动 i 与活动 j 相容。
假设各活动的起始时间和结束时间存储与数组 s 和数组 f 中按结束时间的非减序:
f1 f2 fn 排列。

template<class Type>
//n--活动个数
//s[i]--活动 i 的起始时间
//f[i]--活动 j 结束时间
//A[i]--true:可以进行;false:不可进行
void GreedySelector(int n,Type s[],Type f[],bool A[])
{
    A[1]=true;
    int j=1;
    for(int i=2;i<=n;i++)
    {
        if(s[i]>=f[i])
        {
            A[i]=true;
            j=i;
        }
        else
        {
            A[i]=false;
        }
    }
}

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

这里写图片描述

则选出的活动为:,1,4,8,11


事实上,设E=E={1,2,3 n}为所给的活动集合。由于E中活动按结束时间的非减序排列,故活动 1 具有最早完成时间。首先证明活动安排问题有一个最优解以贪心选择开始的最优解中包含活动 1 。设A E是所给的活动安排问题的一个最优解,且A中活动也按结束时间非减序排列,A中的第一个活动是活动k,若k=1,则A就是一个以贪心选择开始的最优解。若k>1,则设B=A-{k} {1}。由于 f1 fk ,且A中活动是相容的,故B也是最优的。也就是说,B是以贪心选择活动 1 开始的最优活动安排。由此可见,总存在以贪心选择开始的最优活动安排方案。
进一步,在做了贪心选择,即选择了活动 1 后,原问题就简化为对 E 中所有与活动 1 相容的活动进行活动安排的子问题。即若A是原问题的最优解,则 A =A-{1}是活动安排问题 E ={i E: si f1 }的最优解。事实上,如果能找到 E 的一个解 B ,它包含比 A 更多的活动。这与A的最优性矛盾。因此,每一步所做的贪心选择问题都将问题简化为一个更小的与原文一具有相同形势的子问题。


欢迎关注我的微信个人订阅号
这里写图片描述
每天多学一点0.0

你可能感兴趣的:(初学算法)