算法分析五:贪婪算法
一.贪婪算法
二.经典例题
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