003-贪心算法

Posted Java长征记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了003-贪心算法相关的知识,希望对你有一定的参考价值。






003-贪心算法









 

贪心算法




算法概述

       贪心算法也叫贪婪算法,是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优解出发来考虑,它所做出的仅是在某种意义上的局部最优解。(所谓贪心即只看眼前不管未来)


注意:

       贪心方法是一种分级处理方法,首先要根据题意,选取一种量度标准心策略,然后根据量度标准对成本进行排序,再根据题目的约束条件进行选择。对于一个问题可能会有不同的量度标准,选择其中可以获得最优解的量度标准(贪心策略)是贪心法设计的核心问题


贪心算法的基本思想


  •  建立数学模型来描述问题。

  •  把求解的问题分成若干个子问题。

  •  对每一子问题求解,得到子问题的局部最优解。

  •  把子问题的解局部最优解合成原来解问题的一个解。

注意:贪心法要进行正确性证明,证明其不正确举反例即可


贪心法的正确性证明

【个人感觉应该是贪心法的难点之处】

       贪心法正确性证明常用的方法有归纳法(对算法步数归纳、对问题归纳)和交换论证法(从最优解出发,不变坏地替换,得到贪心策略的解)。下面的例子介绍时会详细介绍

  • 活动选择问题——对算法步数归纳

  • 最优装载问题——对问题规模归纳

  • 最小延迟调度——交换论证



贪心算法的性质

  • 贪心选择可以依赖以往所做过的选择,但绝不依赖于将来所作的选择,也不依赖于子问题的解。(区别于动态规划)

  • 贪心算法通常以自顶向下的方式进行,不断迭代做出贪心选择,每做一次贪心选择就将问题简化为规模更小的问题。

【你会发现贪心法其实和动态规划有点相似之处,但也有很大区别】


贪心法的优势

       算法简单,时间和空间复杂性低


> > > >

话不多说直接上栗子,一目了然

经典例子

  • 活动选择问题

  • 最优装载问题

  • 最小延迟调度问题



一一活动选择问题


●问题介绍

       S = {1, 2, … , n}为n 项活动的集合, si , fi 分别为活动 i 的开始和结束时间. 活动i与j相容即si ≥fj 或 sj ≥fi .求最大的相容活动集


贪心策略

策略1:开始时间早的优先排序使 s1≤s2≤…≤sn,从前向后挑选

不正确(反例):

反例:S ={1,2,3 }s1=0, f1=20, s2=2, f2=5, s3=8, f3=15

解(活动1)

003-贪心算法


策略2:占用时间少的优先排序使得 f1-s1≤ f2-s2≤…≤fn-sn,从前向后挑选

不正确(反例)

反例S = { 1, 2, 3 }s1=0, f1=8, s2=7, f2=9, s3=8, f3=15

解(活动2)

003-贪心算法



策略3:结束早的优先排序使 f1≤f2≤…≤ fn,从前向后挑选

解(活动1、3)


伪码:

003-贪心算法

正确性证明(对算法步数归纳)


命题:算法Select执行到第k步,选择k项活动i1=1,i2,…,ik,那么存在最优解 A包含活动 i1=1, i2 ,…, ik .

只要此定理成立,算法至多到第n步得到最优解


归纳证明

设S={1,2,….n}为活动集且f1≤…≤ fn 


归纳基础: k=1, 证明存在最优解包含活动 1 ,k=1, 证明存在最优解包含活动 1

证:任取最优解A, A中活动按截止时间递增排列. 如果A的第一个活动为 j,j ≠1, 用1替换A的活动 j 得到解 A',即A' = (A−{ j }) ∪{1}, 由于 f1 ≤ fj , A' 也是最优解,且含有1.


归纳步骤:

假设命题对k为真, 证明对k+1也为真.

证:算法执行到第 k 步, 选择了活动i1=1,i2, …, ik , 根据归纳假设存在最优解 A包 含i1=1,i2,…,ik , A中剩下活动选自集合S'

S' = { i | i∈S, si ≥ fk }

A = { i1, i2, … , ik } ∪ B

003-贪心算法


证:B是 S'的最优解.(若不然, S' 的最优解为B*, B*的活动比 B多,那么B*∪{1, i2, … , ik } 是 S 的最优解,且比 A的活动多,与 A 的最优性矛盾.)

003-贪心算法

证:将S' 看成子问题,根据归纳基础,存在 S' 的最优解B' 有S' 中的第一个活动 ik+1, 且 |B' | = |B|, 于是

{ i1, i2, ... , ik } ∪ B'= { i1, i2, ... , ik , ik+1 } ∪ ( B'−{ ik+1})也是原问题的最优解

003-贪心算法

程序:

003-贪心算法


时间复杂度

O(n) = O(n)(输入时已排好序)




一一最优装载问题


问题介绍

       n 个集装箱1, 2, … , n 要装上轮船,集装箱 i 的重量为 wi , 轮船装载重量限制为C, 无体积限制. 问如何装使得上船的集装箱最多?假设每个箱子的重量 wi≤C.

【类似于0-1背包问题】


建模

       设 <x1, x2, ... , xn> 表示解向量,xi = 0,1(0代表不装,1代表装)xi = 1表示当且仅当第 i 个集装箱被装上船

003-贪心算法


算法策略

       将集装箱按照重量递增顺序进行排列,轻者优先


正确性证明(对问题规模归纳)

       设集装箱从轻到重记为1, 2, … , n.

命题:对装载问题任何规模为 n 的输入实例,算法得到最优解.


归纳基础:

证:对任何只含 1个箱子的输入实例,贪心法得到最优解. 显然正确.


归纳步骤:

假设对于任何n个箱子的输入实例贪心法都能得到最优解,那么对于任何n+1个箱子的输入实例贪心法也得到最优解.


归纳步骤证明思路

003-贪心算法

假设对于 n 个集装箱的输入,贪心法都可以得到最优解,考虑 输入N = { 1, 2, … , n+1 } 其中 w1 ≤ w2 ≤ … ≤ wn+1.

证:由归纳假设,对于N' = {2, 3, …, n+1},C' = C− w1,贪心法得到最优解 I'.

令I = I '∪{1}


证:I (算法解)是关于 N 的最优解. 若不然,存在包含 1 的关于 N 的最优解 I*(如果 I* 中没有1,用 1 替换 I* 中的第一个元素得到的解也是最优解), 且 |I*|>| I |;那么I*−{1}是 N' 和C' 的解且| I*− {1}| > | I − {1} | = | I' | 与 I'是关于N' 和C' 的最优解矛盾.

003-贪心算法





一一最小延迟调度问题


问题介绍

       客户集合A,∀i∈A,ti 为服务时间,di 为要求完成时间,ti, di为正整数. 一个调度f : A→N,f(i)为客户 i 的开始时间. 求最大延迟达到最小的调度,即求 f 使得

003-贪心算法


贪心策略

       按照 di 从小到大安排,即按完成时间从早到晚安排任务,没有空闲.


伪码

003-贪心算法


正确性证明(交换论证)

       没有空闲时间, 没有逆序. 逆序 ( i, j ): f (i) < f (j) 且 di > dj (逆序即i比j结束时间晚却先执行了


命题:所有没有逆序、没有空闲时间的调度具有相同的最大延迟

证:设 f 没有逆序,在 f 中具有相同完成时间 d 的客户i1, i2, … , ik连续安排, 其开始时刻为 t0, 完成这些任务的时刻是 t,最大延迟为最后任务延迟t−d, 与 i1, i2, … , ik的排列次序无关.t = t0+ (ti1+ ti2+ ...+ tik)

003-贪心算法


证明思想:从一个没有空闲时间的最优解出发,在不改变最优性的条件下,转变为没有逆序的解。


  1. 如果一个最优调度存在逆序,那么存在i < n使得(i,i+1构成一个逆序)

  2. 存在逆序(i,j),j = i + 1,那么交换i和j得到的解的逆序数减一,后面证明这个新的调度仍然最优

  3. 至多经过n(n-1)/2次交换得到一个没有逆序的最优调度


证:交换相邻逆序仍旧最优

设 f1是一个任意最优解,存在相邻逆序( i, j ) . 交换 i 和 j 的顺序, 得到解 f2. 那么f2的最大延迟不超过 f1的最大延迟.

  1. 交换 i, j 与其他客户延迟时间无关

  2. 交换后不增加 j 的延迟,但可能增加 i的延迟

  3.  i 在 f2的延迟小于 j 在 f1 的延迟 ,因此小于f 1的最大延迟 r


003-贪心算法


程序:

003-贪心算法


时间复杂度为

O(nlogn) + O(n) = O(nlogn)



【可以看出贪心法的程序设计和思路其实很简单,个人感觉难点就在于证明贪心策略的正确性,如果一个问题可以用贪心法解决的话,首选贪心法】


















Thank    u

--End--

                    

谢谢!

                        



以上是关于003-贪心算法的主要内容,如果未能解决你的问题,请参考以下文章

算法| 贪心算法:如何用贪心算法实现Huffman压缩编码?

程序员算法基础——贪心算法

贪心思想

算法基础--贪心算法

贪心算法学习,附由贪心算法引发的人生感悟。

算法贪心算法(0-1背包问题)