贪 心 算 法
- 格式:pdf
- 大小:179.94 KB
- 文档页数:7
算法设计与分析中的贪心算法与回溯法算法设计与分析领域中,贪心算法和回溯法是两种常用的解题方法。
本文将介绍这两种算法,并比较它们在不同场景下的优势和劣势。
一、贪心算法贪心算法是一种在每一步都选择当前最优解的策略,希望通过局部最优解的选择最终达到全局最优解。
贪心算法的实现较为简单,时间复杂度较低,适用于解决一些最优化问题。
贪心算法的基本思想是每次都选择当前状态下的最优解,并将其加入到解集中。
例如,在求解最小生成树的问题中,贪心算法会选择当前具有最小权值的边,并将其添加到最终结果中,直到生成树完成。
然而,贪心算法的局限性在于它只考虑了当前的最优解,无法保证找到全局最优解。
在某些问题中,贪心算法可能会陷入局部最优解而无法跳出。
因此,需要在具体问题中综合考虑问题的性质和约束条件来确定是否适合采用贪心算法。
二、回溯法回溯法是一种通过不断尝试可能的步骤来寻找问题解的方法。
它通常基于递归的思想,在每一步都尝试所有的可能选择,并逐步构建解空间,直到找到解或确定无解。
回溯法的核心思想是深度优先搜索,通过遍历解空间树来寻找解。
在每一步,回溯法都会考虑当前状态下的所有可能选择,并递归地进入下一步。
如果某一步的选择无法达到目标,回溯法会回退到上一步进行其他可能的选择。
回溯法常用于解决一些全排列、子集和组合等问题。
例如,在解决八皇后问题时,回溯法通过逐个放置皇后并进行合法性判断,直到找到所有解或遍历完所有可能的情况为止。
然而,回溯法的缺点在于其时间复杂度较高,其搜索过程包含了大量的重复计算。
因此,在使用回溯法解决问题时,需注意适当剪枝以减少搜索空间,提高算法效率。
三、贪心算法与回溯法的比较贪心算法和回溯法都是常用的算法设计与分析方法,但其适用场景和效果有所差异。
贪心算法在解决问题时能够快速找到局部最优解,并且具有较低的时间复杂度。
它适用于一些满足最优子结构性质的问题,例如最小生成树、单源最短路径等。
然而,贪心算法无法保证一定能找到全局最优解,因此需根据具体问题的特点来判断是否使用。
贪心算法实验报告心得前言贪心算法是一种常见且重要的算法设计思想,通过每一步都选择当下最优的解决方案,以期望最终得到全局最优解。
在学习与实践贪心算法的过程中,我有了许多心得与体会。
什么是贪心算法?贪心算法是一种求解问题的算法思想,它的特点是每一步都选择当前最优的解决方案,而不考虑该选择对以后步骤的影响。
贪心算法通常适用于可以将问题分解为若干个子问题,并且通过每次选择当前最优解来得到整体最优解的情况。
贪心算法的基本步骤贪心算法的基本步骤可以总结为以下几个方面:1.确定问题的解空间,并找到问题的最优解。
贪心算法通常通过穷举法或者利用问题的特殊性质来确定解空间。
2.制定贪心策略。
贪心算法的核心是确定每一步选择的贪心策略,即选择当前最优解。
3.确定贪心策略的正确性。
贪心算法的一个关键问题是如何证明贪心策略的正确性。
可以通过数学证明、反证法或者举反例等方式来进行证明。
4.实现贪心算法。
将贪心策略转化为实际可执行的算法步骤,编写代码来求解问题。
贪心算法实验结果分析在本次实验中,我使用贪心算法解决了一个经典问题:找零钱问题(Change-Making Problem)。
给定一定面额的硬币和需找的金额,我们的目标是使用最少的硬币来完成找零钱。
贪心算法的思路是每次选择面额最大的硬币进行找零。
实验设计1.实验输入:我设计了多组输入来测试贪心算法的性能。
每组输入包括一个需找的金额和一个硬币集合。
2.实验输出:对于每组输入,贪心算法输出一个最优的硬币找零方案,以及使用的硬币数量。
3.实验评价:我使用了实际需找金额与贪心算法计算得到的找零金额的差值来评估算法的准确性,并统计了算法的时间复杂度。
实验结果从多组实验结果中可以观察到,贪心算法在大部分情况下给出了正确的找零金额,并且算法的时间复杂度较低。
结果分析贪心算法在找零钱问题中的应用是合理的。
每次选择面额最大的硬币进行找零,可以快速接近最优解,并且相对其他算法具有较低的时间复杂度。
我们可以看到,在活动选择问题中,除了以活动结束时间最早为标准来选择活动的最大兼容集合外,还有三种思路:
1.选择生存周期最短的活动;
2.选择与余下的活动重叠最少的活动;
3.选择开始时间最早的活动;
这三种选择都可能让选择出来的兼容活动的最大集合不是最优解。
下面我们举例说明:
(a).选择生存周期最短的活动:
我们选择第一行的活动,构成了结果。
但这并不是最优解。
因为选择第二行的两个活动,明显是最优解。
(b). 选择与余下的活动重叠最少的活动:
我们选择第一行的第一个活动,然后选择第一行的第二个活动(选这个是毋庸置疑的),最后选第一行的第三个。
我们可以发现最优解是第二行(兼容4个活动)而不是第一行。
(c). 选择开始时间最早的活动:
我们选择第一行,那么结果便是只有一个兼容活动的集合。
明显不是最优解。
第二行才是最优解。
贪心算法并不总能求得问题的整体最优解。
但对于活动安排问题,贪心算法却总能求得的整体最优解,即它最终所确定的相容活动集合A的规模最大。
这个结论可以用数学归纳法证明。
贪心算法的基本要素贪心算法是一种非常简单但有效的算法设计策略,可用于解决一些最优化问题。
它通过找到每个阶段的局部最优解,并将其累积以得到全局最优解。
在实践中,贪心算法通常易于实现且效率较高。
下面将介绍贪心算法的基本要素。
1.最优子结构性质:贪心算法的最优子结构性质是贪心策略的基础。
它表示问题的最优解可以通过在每个阶段选择局部最优解来得到。
换句话说,问题的最优解包含了其子问题的最优解。
2.贪心选择性质:贪心算法的贪心选择性质是指在每个阶段选择局部最优解,以期望达到全局最优解。
这意味着贪心算法不会回退或改变之前所做的选择。
3.贪心算法的设计:贪心算法通常由以下步骤组成:(a)将问题分解为若干个子问题,并找到子问题的最优解;(b)找出每个子问题的局部最优解,并将其融合到全局最优解中;(c)使用贪心选择策略进行迭代,直到获得全局最优解。
4.贪心算法的正确性证明:在设计贪心算法时,需要证明贪心选择的局部最优解也是全局最优解。
这通常涉及数学归纳法、反证法或其他数学证明方法。
通过正确性证明,可以确保贪心算法能够正确地解决问题。
5.问题的适用性:贪心算法通常适用于满足最优子结构性质且贪心选择性质成立的问题。
但并非所有问题都适用于贪心算法。
在实践中,需要仔细分析问题的特点和要求,确定是否可以使用贪心算法求解问题。
1.零钱找零问题:给定一定面额的硬币,如何使用最少数量的硬币找零?贪心策略是在每个阶段选择面额最大的硬币,直到找零完毕。
2.活动选择问题:给定一组活动的开始时间和结束时间,如何安排最多的互不重叠活动?贪心策略是在每个阶段选择结束时间最早的活动,并删除与之冲突的活动。
3.部分背包问题:给定一组物品以及它们的重量和价值,如何选择物品以在限定重量内获得最大的总价值?贪心策略是计算每个物品的单位价值,并选择单位价值最高的物品放入背包中。
4.最小生成树问题:给定一个无向图,如何选择其中的边以连接所有顶点且总权重最小?贪心策略是在每个阶段选择权重最小的边,并保证该边不会形成环路。
有人说贪心算法是最简单的算法,原因很简单:你我其实都很贪,根本不用学就知道怎么贪。
有人说贪心算法是最复杂的算法,原因也很简单:这世上会贪的人太多了,那轮到你我的份?贪心算法详解贪心算法思想:顾名思义,贪心算法总是作出在当前看来最好的选择。
也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。
当然,希望贪心算法得到的最终结果也是整体最优的。
虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。
如单源最短路经问题,最小生成树问题等。
在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。
贪心算法的基本要素:1.贪心选择性质。
所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。
这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。
动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。
对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。
2. 当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。
问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。
贪心算法的基本思路:从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。
当达到算法中的某一步不能再继续前进时,算法停止。
该算法存在问题:1. 不能保证求得的最后解是最佳的;2. 不能用来求最大或最小解问题;3. 只能求满足某些约束条件的可行解的范围。
实现该算法的过程:从问题的某一初始解出发;while 能朝给定总目标前进一步do求出可行解的一个解元素;由所有解元素组合成问题的一个可行解;用背包问题来介绍贪心算法:背包问题:有一个背包,背包容量是M=150。
贪心算法在最优化问题中的应用研究第一章:引言贪心算法是在最优化问题中被广泛应用的一种算法。
在计算机科学领域中,贪心算法是一种启发式算法,通过在每个步骤中选择最优解决方案来达到整体最优解决方案。
贪心算法的特点是该算法快速简单且易于理解。
在不同的最优化问题中,贪心算法具有不同的应用方法和实现方式。
本文将介绍贪心算法的基本原理和应用方法,并从实际问题出发,分析贪心算法在最优化问题中的应用实例。
第二章:贪心算法基本原理贪心算法是一种求解最优解的启发式算法。
贪心算法在每个步骤中选择当前状态下的最优解,使得整体解决方案达到最优化。
贪心算法与动态规划、分支界限等算法相比较,贪心算法具有简单快速的特点。
贪心算法的过程如下:1、定义最优解。
2、根据问题定义选择一个最优解策略。
3、根据最优策略,在当前状态下选择最优的解。
4、对于已选择的最优解,在下一个状态下重复步骤3,直到达到最优解。
贪心算法的正确性需要证明,即要证明每一步选择的最优解可以达到整体最优解。
第三章:贪心算法应用方法针对不同的最优化问题,贪心算法具有不同的应用方法。
本节将从两个方面来介绍贪心算法应用的两种方法。
1、构造法贪心算法通过构造法实现。
通常情况下,构造法通过从剩余选项中选择当前状态下的最优解。
举例说明,对于背包问题,贪心算法以价值单位最高为准则优先选取物品装入背包中。
在霍夫曼编码问题中,贪心算法选择以最小的频率为基准选择编码,这样可以使总编码长度最小。
2、优化法贪心算法通过优化法实现。
通常情况下,优化法通过贪心算法的思路对问题进行重构。
这样,在选择最优状态时,将避免一些不必要的无效状态。
举例说明,对于旅行推销员问题,贪心算法可以通过选择离当前节点距离最近的邻居节点,避免重复和无效的状态。
第四章:应用实例贪心算法在不同的实际问题中得到了充分的应用。
在本章中,将通过两个实际问题来展示贪心算法的具体应用。
1、硬币找零贪心算法在硬币找零问题中得到了应用。
对贪心算法的概述和研讨福州第一中学高一(8)班汪涛指导老师:陈颖算法总览当一个问题具有“最优子结构”时,我们可以采用动态规划法解决该问题。
但是有的时候,贪心算法可以更好的处理该类问题。
总体上看,贪心算法是一种高效的、不稳定的算法;但是它在解决问题时有很多独特的优良性质,掌握贪心算法有时可以非常迅速的获得最优解或近似最优解。
关键字:贪心算法(贪婪算法),贪心算法的应用举例,Object Pascal,快速算法,不稳定算法,信息学奥赛。
何时采用何时能,又何时应该采用贪心算法呢?一般认为,凡是经过数学归纳法证明可以采用贪心算法的情况,都应该采用它。
因为它的效率是很高的。
贪心算法的弱点在于它的不稳定性,即有时它不总能返回最优解。
那么能采用贪心算法的问题具有怎样的性质呢?(何时采用贪心算法)1、它具有和动态规划问题相似的性质,即分治法中的“最优子结构”性质,即每个子问题的最优解的集合就是整体最优解。
这是必须的性质,因为贪心算法解决的问题流程就需要依序研究每个子问题,然后综合之得出最后结果。
不能采用分治法解决的问题,是理论上是不能使用贪心算法的。
而且,必须拥有最优子结构性质,才能保证贪心算法返回最优解。
2、它必须具有一种特殊的“贪心选择性”。
这种性质类同于“最优子结构”性质,但又有一些小的差别。
我们知道,在动态规划中,每一个父问题结果的得出需要它的子问题作为条件;但是“贪心选择性”则不需要;贪心选择性所做的是一个非线性的子问题处理过程,即一个子问题并不依赖于另一个子问题,但是子问题间有严格的顺序性。
要证明一个问题具有“贪心选择性”,就必须证明每一步所做的贪心选择最终导致一个问题的整体最优解。
这也是必须的性质。
如果一个问题具有上述两个性质,理论上就应该采用贪心算法。
处理流程经由贪心算法处理的问题需要经过排序。
即把“最贪心”的子结果排在序列的最前面,一直到“最不贪心的”。
这是处理问题的第一步。
然后依序解决问题而得出最终结果。
贪⼼算法总结简介贪⼼算法(英⽂:greedy algorithm),是⽤计算机来模拟⼀个“贪⼼”的⼈做出决策的过程。
这个⼈⼗分贪婪,每⼀步⾏动总是按某种指标选取最优的操作。
⽽且他⽬光短浅,总是只看眼前,并不考虑以后可能造成的影响。
可想⽽知,并不是所有的时候贪⼼法都能获得最优解,所以⼀般使⽤贪⼼法的时候,都要确保⾃⼰能证明其正确性。
本⽂主要介绍,在解决诸多贪⼼算法的问题之后的⼼得。
常⽤场景最常见的贪⼼算法分为两种。
「我们将 XXX 按照某某顺序排序,然后按某种顺序(例如从⼩到⼤)选择。
」。
「我们每次都取 XXX 中最⼤/⼩的东西,并更新 XXX。
」(有时「XXX 中最⼤/⼩的东西」可以优化,⽐如⽤优先队列维护)第⼀种是离线的,先处理后选择,第⼆种是在线的,边处理边选择。
常见的出题背景为:确定某种最优组合(硬币问题)区间问题(合理安排区间)字典序问题最值问题A最优组合硬币问题是贪⼼算法⾮常经典的题⽬,关于最优组合问题,我认为主要分为两种类型:简单 -- 直接排序之后按照某种策略选取即可复杂 -- 除了按照贪⼼策略外,还需要进⾏某些处理或者模拟硬币问题硬币问题有1元、5元、10元、50元、100元、500元的硬币各C1、C5、C10、C50、C100、C500枚。
现在要⽤这些硬币来⽀付A元,最少需要多少枚硬币?假设本题⾄少存在⼀种⽀付⽅法。
0≤C1、C5、C10、C50、C100、C500≤1090≤A≤109本题是上述说的简单类型的题⽬,简⽽⾔之要使得硬币最少,则优先使⽤⼤⾯额的硬币。
因此本题的解法便⾮常清晰了,只需要从后往前遍历⼀遍即可(默认为硬币已经按⾯额⼤⼩进⾏排序)const int V[6] = {1, 5, 10, 50, 100, 500};int A, C[6]; // inputvoid solve(){int ans(0);for (int i = 5; i >= 0; -- i){int t = min(A / V[i], C[i]);A -= t * V[i];ans += t;}cout << ans << '\n';}零花钱问题POJ3040 AllowanceDescriptionAs a reward for record milk production, Farmer John has decided to start paying Bessie the cow a small weekly allowance. FJ has a set of coins in N (1 <= N <= 20) different denominations, where each denomination of coin evenly divides the next-larger denomination (e.g., 1 cent coins, 5 cent coins, 10 cent coins, and 50 cent coins).Using the given set of coins, he would like topay Bessie at least some given amount of money C (1 <= C <= 100,000,000) every week.Please help him ompute the maximum number of weeks he can pay Bessie.Input* Line 1: Two space-separated integers: N and C* Lines 2..N+1: Each line corresponds to a denomination of coin and contains two integers: the value V (1 <= V <= 100,000,000) of the denomination, and the number of coins B (1 <= B <= 1,000,000) of this denomation in Farmer John's possession.Output* Line 1: A single integer that is the number of weeks Farmer John can pay Bessie at least C allowanceSample Input3 610 11 1005 120Sample Output111这题的题⽬⼤意是:农场主每天都要给贝西⾄少为C的津贴。
【贪心算法】思想 & 基本要素 & 贪心算法与局部最优 & 贪心算法与动态规划的区别 & 运用贪心算法求解问题
首先我们先代入问题来认识一下贪心算法涉及的问题
找钱问题
给顾客找钱,希望找零的钞票尽可能少,零钱种类和数量限定
找钱问题满足最优子结构
最快找零(贪心):为得到最小的找零次数,每次最大程度低减少零额活动安排问题
设个活动都需要使用某个教室,已知它们的起始时间和结束时间,求合理的安排使得举行的活动数量最多
贪心:使得每次安排后,教室的空闲时间最多
解决过程如下:
贪心算法求得的相容活动集是最大的
第一步:证明最优解中包含结束时间最早的活动
设相容集 A 是一个最优解,其结束最早的活动为 a,则 ( A - { a }) U { 1 } 也是一个最优解
第二步:证明去掉结束时间最早的活动后,得到的子问题仍是最优的:反证法
理解贪心算法
贪心算法总是做出当前最好的选择
贪心选择的依据是当前的状态,而不是问题的目标
贪心选择是不计后果的
贪心算法通常以自顶向下的方法简化子问题
贪心算法求解的问题具备以下性质
贪心选择性质:问题的最优解可以通过贪心选择实现
最优子结构性质:问题的最优解包含子问题的最优解
贪心选择性质的证明
证明问题的最优解可以由贪心选择开始
即第一步可贪心
证明贪心选择后得到的子问题满足最优子结构
即步步可贪心
背包问题
问题描述:给定 n 个物品和一个背包。
物品 i 的重量为 Wi ,价值为 Vi ,背包的容量为 c ,问如何选择物品或物品的一部分,使得背包中物品的价值最大?
当 n = 3 ,c = 50
0-1背包问题:装入物品2、3,最大价值220
背包问题:装入物品1、2和2-3的物品3,最大价值240(贪心算法)贪心算法无法求解0-1背包问题,按贪心算法,0-1背包问题将装入物品1和2
贪心与局部最优
思考:为什么0-1背包可以用动态规划?而不能用贪心算法
贪心易陷入局部最优
好比“以最快的速度下山”,每步都选择最快不见得一定到达山脚
局部最优是指解在一定范围或区域内是最优的,或求解问题的方法在一定限制条件下是最优的
一般的启发式算法、贪心算法或局部算法都很容易产生局部最优
局部最优通常是无法查证的
获得局部最解的复杂度远低于全局最优解
找钱问题:15元找零11之后,不存在面值为4元的零钱
0-1背包问题:50容量的背包装入前两个物品仍剩余20容量的空间活动安排问题:若限制教室使用的总时间
贪心算法与动态规划
贪心算法和动态规划都具有最优子结构
贪心算法是自顶向下的,只查看了当前状态;而动态规划自底向上地求解了最优解包含的所有子问题
最优装载
问题描述:一批集装箱要装上一艘载重量为 c 的轮船,其中集装箱 i 的重量为 Wi ,不考虑体积,将尽可能多的集装箱装上轮船贪心:重量轻者先装
思考:与0-1背包问题有什么不同?
设 x = (x1, x2, … , xn) 是最优装载问题的最优解(贪心算法)贪心选择性质:设y = (y1, y2, … , yn) 是一个最优解,其第一个不为0的选择为 yk = 1,则将物品 k 替换成物品1,仍满足容量限制,替换方案就构成了原问题的另一个最优解
最优子结构性质:考虑去掉物品1后的子问题
哈夫曼编码
Huffman编码是一种可变字长编码,一种构建极小多余编码的方法
一篇包含6种字符的文档中
将串001011101解码为aabe
定义平均码长为
求文档 C 的哈夫曼编码就等价于构建一棵最优完全二叉树,使得平均码长最小
即文档 C 的最优前缀码
贪心算法:依次将最小频率的节点两两合并
单源最短路径
问题描述:设一个带权的有向图 G = (V, E)
求从源顶点 V1属于 V 到其他顶点的最短路径
Dijkstra 算法又称为标号法
T标号:临时标号(tentative label),表示到源顶点的路径还可以进一步降低,有待探查
P标号:永久标号(permanent label),表示已经找到源顶点的最短路径,不再探查
当所有顶点的标号变成P标号时,算法结束,即算法最多需要 n - 1 步初始:给起点一个 P 标号 0,其他顶点为无穷大的 T 标号
更新:若顶点 Vi 最近获得了P标号,考查与其有弧 eij 相连的顶点Vj,若 Vj 仍是 T 标号,更新其 T 标号为
决策:在所有 T 标号中,选择一个值最小的顶点,令其变为 P 标号Dijkstra 算法为什么没有陷入局部最优?
贪心:决策总是在所有T标号的顶点中选择最小
最小生成树
给定无向图 G = (V, E),称G‘ = (V’,E‘)是 G 的一个子图,若V’ 包含于 V,E’包含于 E。
若V’ = V,则称G‘ 是 G 的一个支撑子图
若一个无向图是连通的,且无回路,则称这个图为一个树
给定图 G ,若 G 的一个支撑子图 T 是一个树,则称 T 为 G 的一个支撑树
若 G 是一个带权的图,则称权最小的支撑树为 G 的最小生成树
Most Small Tree:设 G = (V, E)是一个连通带权图,设 (u , v) 包含于 E, u 包含于 U,v 包含于 V - U,其中 U 属于 V ,且 (u , v) 是这样的边中权最小的一条边,则一定存在 G 的一棵最小生成树包含 (u , v) 这条边
贪心:每次选取已观察顶点集与未观察顶点集之间具有最小权的边,将所有边按权从小到大排序,依次添加到最小生成树中,且不形成回路多机调度问题
问题描述:给定 n 个独立的作业要在 m 台机器上加工,求合理的调度方案使得加工时间最短
贪心:将最长时间的作业安排到最闲的机器上
贪心选择:
只剩一个作业时,应安排在最闲的机器上
最后安排时间最短的作业
贪心算法总是选择当前最有利的方案,因而容易陷入局部最优解
贪心算法可解的问题应具有贪心选择性质和最优子结构性质
贪心算法的证明分两步,第一步证明可将最优解替换成以贪心选择开始,第二步证明去掉贪心选择后满足最优子结构
贪心算法的复杂性很低
贪心算法无法求解0-1背包问题,按贪心算法,0-1背包问题将装入物品1和2
服务问题我们现在的每个人接受服务的时间就是自己和之前所有人时间的总和,而当更高一级的客户来的时候就会自动地排在现在接受服务的人的后面,后面所有的人次序就会自动的像后面加一。
b[k].vlue=a[i].s; b[k++].flag=0;--0代表开始时间
printf("%d,%d",a[i].start,a[i].finish);
}。
这些活动使用同一个资-源(如教室)。
该资-源一次只能被一个活动占用。
每个活动
if(courses[max_i][0] courses[i][0]){
时间串行的任务,按子任务来分解,即每一步都是在前一步的基础上再选择当前的最优解。
(2)建立数组 dist[i],存源到 i 点的距离。
若源与点 i 直接相连,则 dist[i] 等于权重,若源与 i 不直接相连,则dist[i]=∞。
1.若a[i]v,则将a[i]-v张从第I堆移动到第I+1堆;
result.append(goods(a_goods.id, capacity, a_goods.value * capacity - a_goods.weight))。