幽魂倪

导航

算法分析五:贪婪算法

一.贪婪算法

 

 二.经典例题

1.找零问题

问题:假如有100元,有1元,5元,8元,18元,请问找零的最小张数?

分析:找零问题可以考虑动态规划问题(前n种纸币最少的找零张数)。贪婪算法:在不大于100的情况下,那币值越大的纸张越好。(首先对找零钱的币值大小排序:有大到小)

      如题,100中先拿18元的,最多拿5张,剩余10元,再拿8元的,最多拿1张,剩余2元,5元不够,拿1元的两张。共5+1+2=8张。

证明:

三,找换硬币的贪心算法的正确性证明

在进行证明之前,先提一个性质:对于最优解而言,如果使用了面值为 ci 的硬币去找零,那么 ci 最多只能使用 c-1 个。

因为我们的目标是使用 最少数目的硬币,对于最优解而言,如果使用了面值为 ci 的硬币去找零,那么 ci 最多只能使用 c-1 个。

why? 假设使用了 c 个(大于c个也一样)面值为 ci 的硬币去找零,那我为什么不用一个 面值为 ci+1 的硬币去找呢?

这样,我就可以用更少的硬币数啊(c>1)。所以说,在最优解里面,如果使用了面值为 ci 的硬币去找零,那么 面值为ci 的硬币 最多只能使用 c-1 个。

OK,下面再次用到剪枝的思想来证明贪心选择的正确性了。

总体思路是:先考察一个最优解,然后证明可对该解进行修改,使其采用贪心选择,这个选择将原问题变成一个相似的、但是“更小”的问题。(这里说的“更小”是一种抽象,并不是具体意义上的更小)

k 是可找换的硬币的种类数,n 是需要找换的价值,a(i)表示使用多少个 面值为 ci 的硬币。假设硬币已经按面值从小到大排序。

对于贪心选择而言,我们一定会选择面值为 c^j 的硬币,因为:我们的贪心策略就是总是优先选择 面值最大的硬币。

我们的目标是证明,对于所有的贪心选择而言,它们都不可能产生最优解。

对于非贪心选择,是不会选择 面值为 c^j (or higher)的硬币的。非贪心选择使用的硬币如下:

其中,a(i)表示使用了 a(i)个 面值为 ci 的硬币,总数之和是n。别忘了,n 就是需要找零的数目

而对于贪心选择而言,如果面值为 c^j 的硬币可用(当 n>=c^j 时),我们是优先使用 面值为 c^j 的硬币的。

因此有:

这说明,在面值为 c^j 的硬币 可用的情况下,换句话说:在 c^j <=n 的情况下,贪心选择没有使用 c^j 嘛。(选择了的话,那就是贪心选择了嘛...~)

 这里就会有矛盾了,根据前面提到的性质:有, a(i) <= c-1

 

 

从而,证明了贪心选择的正确性。

再来理解下它:总体思路是:先考察一个最优解,然后证明可对该解进行修改,使其采用贪心选择,这个选择将原问题变成一个相似的、但是“更小”的问题。(这里说的“更小”是一种抽象,并不是具体意义上的更小)

这里的最优解是:非贪心选择下的某个最优解,然后剪枝:将非贪心选择下的某个元素去掉,然后添入贪心选择的那个元素。其实就是下面的这个公式。

              从而得到了一个更优的问题。

 

时间复杂度:T(n)=排序复杂度 + 执行算法复杂度。O(n)

2.调度问题

问题:例如,设我们有四个作业和相关的运行时间,(j1     t1=15   ,j12    t2=8,    j3     t3=3,   j4     t4=10),该调度的总代价C为 : C = Σ(k=1 到 N)(N - k +1) t(ik). 问如何做能使调度总代价最小?

分析:对C的进一步变形:C=(N+1)Σ(k=1到N)t(ik) — Σ(k=1到N) K*t(ik), 可以看出第一个求和与作业的排序无关,因此只有第二个求和影响到总代价。

   考虑贪心性质,K为递增变量,考虑到第二个求和越大越好,因此将t(ik)按从小到大排序,即可得到该问题的最佳调度解决方法。

针对多处理器的情况:Np hard 问题。

证明:

时间复杂度:

3.Huffman编码

问题:例如,有如下字符 ,频率,a,10  e,15   i,12   s,3   t,4     空格,13    换行,1   请问如何计算使得总位数最小? 

分析:Huffman算法。

证明:

设某编码加权和为sigma(Ai*Pi),若存在更优的非H编码,不妨设其中与H编码中权重Pi的位置Ai与Pj的位置Aj调换位置(Pi>Pj),则有Pi*Aj+Pj*Ai>Pi*Ai+Pj*Aj,整理得(Pi-Pj)*Aj>(Pi-Pj)*Ai,即Aj>Ai,与H编码矛盾,因此不存在更优的编码。

4.Prim算法

问题:解决最小生成树的问题:  输入无向带权图连通图G(V,E),输出Tree (V,E') E'属于E ,  |E'|=n-1 .

分析:一.

    算法正确性分析 1.Prim: 可产生一个生成树 T*.(条件 1.  无回路 2.  n-1条边)  2 T* 是 mst.

      二.

    I Empty-cut 空割性质:G是非连通的  等价于  存在cut(A,B)个数为0.

    II 从A,B中各取一个点,u,v     , u,v不相连 可推出  G不连通。

       III Double—cross 性质 : 如果在割边存在回路,那么回路上的割边至少为2条(偶数条)。

                  IV lonely—cut 性质:如果e是A,B的唯一割边,则e不会出现在回路上。

证明:

  二.1.X从小到大直到 V,会不会出现 X 不等于 V。(假如X不等于V: 则割边为0,即图不连通与题意相矛盾)

    2.n—1条边无回路出现。(利用double—cut 性质)如果有两条割边则必定有回路出现,Prim,算法过程中可看成最多产生N-1 条割边,即无环路产生。

      三.T* is mst.

   cut性质(贪心性):在G的任意cut中,最小权值的边一定在mst中。

   cut性质 推出 Prim可以产生mst.

  假设:e是最小割边,但没有被选中,产生了mst,T**.

  那么必定有权值最小的割边可以替换的边,由此产生的T* 必定小于T**,证毕。

找零问题的证明:参考 https://www.cnblogs.com/hapjin/p/5575112.html

posted on 2020-05-12 19:18  幽魂倪  阅读(555)  评论(0编辑  收藏  举报