贪心算法(greedy algorithm,又称贪婪算法)详解(附例题)

您所在的位置:网站首页 最小化指派问题例题 贪心算法(greedy algorithm,又称贪婪算法)详解(附例题)

贪心算法(greedy algorithm,又称贪婪算法)详解(附例题)

2024-07-17 01:28| 来源: 网络整理| 查看: 265

目录 基本思想一)概念二)找出全局最优解的要求三)求解时应考虑的问题四)基本步骤五)贪心策略选择六)实际应用 1.零钱找回问题2.背包问题3.哈夫曼编码4.单源路径中的Djikstra算法5.最小生成树Prim算法

基本思想 贪心算法(Greedy Algorithm)是一种在求解问题时,每一步都选择当前最优解,以期望最终得到全局最优解的算法思想。贪心算法的基本思想可以总结为“每一步都做出一个局部最优的选择,最终就能得到全局最优解”。

贪心算法通常包含以下关键步骤:

找到可选的子问题: 首先,将原问题拆分成一系列可选的子问题或决策。

找到局部最优解: 对每个子问题,找到一个局部最优解。这个局部最优解应该是一个贪心选择,即在当前状态下选择最优的方式。

合并子问题的解: 将各个子问题的局部最优解合并起来,得到原问题的解。

检查解的有效性: 最后,检查得到的解是否满足问题的约束和要求。如果满足,就认为得到了问题的解。

贪心算法适用于一些特定类型的问题,通常要求问题具有贪心选择性质(即每一步的选择都是最优的),以及最优子结构性质(即问题的最优解可以通过子问题的最优解推导得出)。然而,贪心算法不一定能够求解所有问题,有些问题可能需要更复杂的算法来解决。

经典的贪心算法问题有找零钱问题、活动选择问题、背包问题中的部分背包等。贪心算法在求解这些问题时,通常能够得到接近最优解的结果,但并不保证一定能够得到全局最优解。

总之,贪心算法是一种基于每一步的局部最优选择来求解问题的思想,适用于一些满足贪心选择性质和最优子结构性质的问题。

一)概念

贪心算法(Greedy Alogorithm)又叫登山算法,它的根本思想是逐步到达山顶,即逐步获得最优解,是解决最优化问题时的一种简单但是适用范围有限的策略。

贪心算法没有固定的框架,算法设计的关键是贪婪策略的选择。贪心策略要无后向性,也就是说某状态以后的过程不会影响以前的状态,只与当前状态有关。

贪心算法是对某些求解最优解问题的最简单、最迅速的技术。某些问题的最优解可以通过一系列的最优的选择即贪心选择来达到。但局部最优并不总能获得整体最优解,但通常能获得近似最优解。

在每一步贪心选择中,只考虑当前对自己最有利的选择,而不去考虑在后面看来这种选择是否合理。

二)找出全局最优解的要求

在遇见问题时如何确定是否可以使用贪心算法解决问题,那么决定一个贪心算法是否能找到全局最优解的条件是什么呢?其实就是以下两点:

最优子结构(optimal subproblem structure,和动态规划中的是一个概念)最优贪心选择属性(optimal greedy choice property) 三)求解时应考虑的问题

1.候选集合S 为了构造问题的解决方案,有一个候选集合C作为问题的可能解,问题的最终解均取自于候选集合C。 2.解集合S 随着贪心选择的进行,解集合不断扩展,直到构成一个满足问题的完整解。 3.解决函数solution 检查解集合是否构成问题的完整解。 4.选择函数select 即贪心策略,这是贪心算法的关键,它指出哪个候选对象有希望构成成问题的解。 5.可行函数feasible 检查解集合中加入一个候选对象是否可行,即解集合扩展后是否满足约束条件。

四)基本步骤

贪心算法使用基本步骤: 1.从问题的某个初始解出发 2.采用循环语句,当可以向求解目标前进一步时,就根据局部最优策略,得到一个部分解,缩小问题的范围或规模。 3.将所有的部分解综合起来,得到问题的最终解。

五)贪心策略选择

贪心算法的原理是通过局部最优来达到全局最优,采用的是逐步构造最优解的方法。在每个阶段,都做出一个看上去最优的,决策一旦做出,就不再更改。

要选出最优解可不是一件容易的事,要证明局部最优为全局最优,要进行数学证明,否则就不能说明为全局最优。

很多问题表面上看来用贪心算法可以找到最优解,实际上却把最优解给漏掉了。这就像现实生活中的“贪小便宜吃大亏”。所以我们在解决问题的时候,一定要谨慎使用贪心算法,一定要注意这个问题适不适合采用贪心算法。

贪心算法很多时候并不能达到全局最优,为什么我们还要使用它呢?

因为在很多大规模问题中,寻找最优解是一件相当费时耗力的事情,有时候付出大量人力物力财力后,回报并不与投入成正比。在这个时候选择相对最优的贪心算法就比较经济可行了。有的问题对最优的要求不是很高,在充分衡量付出和回报后,选择贪心算法未尝不是一种不错的选择呢。

六)实际应用 1.零钱找回问题

这个问题在我们的日常生活中就更加普遍了。假设1元、2元、5元、10元、20元、50元、100元的纸币分别有c0, c1, c2, c3, c4, c5, c6张。现在要用这些钱来支付K元,至少要用多少张纸币?用贪心算法的思想,很显然,每一步尽可能用面值大的纸币即可。在日常生活中我们自然而然也是这么做的。在程序中已经事先将Value按照从小到大的顺序排好。 下面展示一些 内联代码片。

#include #include using namespace std; const int N=7; int Count[N]={3,0,2,1,0,3,5}; int Value[N]={1,2,5,10,20,50,100}; int solve(int money) { int num=0; for(int i=N-1;i>=0;i--) { int c=min(money/Value[i],Count[i]); money=money-c*Value[i]; num+=c; } if(money>0) num=-1; return num; } int main() { int money; cin>>money; int res=solve(money); if(res!=-1) cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3