贪心算法详解分析

合集下载

C语言贪心算法分析

C语言贪心算法分析
通过几个具体的例子来慢慢理解它: 1.活动选择问题
这是《算法导论》上的例子,也是一个非常经典的问题。有 n 个需要在同一 天使用同一个教室的活动 a1,a2,…,an,教室同一时刻只能由一个活动使用。每 个活动 ai 都有一个开始时间 si 和结束时间 fi 。一旦被选择后,活动 ai 就占据半 开时间区间[si,fi)。如果[si,fi]和[sj,fj]互不重叠,ai 和 aj 两个活动就可以被安排在 这一天。该问题就是要安排这些活动使得尽量多的活动能不冲突的举行。例如下 图所示的活动集合 S,其中各项活动按照结束时间单调递增排序。
五、贪心选择性质
所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的
选择,换句话说,当考虑做何种选择的时候,我们只考虑对当前问题最佳的选择 而不考虑子问题的结果。这是贪心算法可行的第一个基本要素。贪心算法以迭代 的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的 子问题。对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步 所作的贪心选择最终导致问题的整体最优解。
七、例题分析
如果大家比较了解动态规划,就会发现它们之间的相似之处。最优解问题大 部分都可以拆分成一个个的子问题,把解空间的遍历视作对子问题树的遍历,则 以某种形式对树整个的遍历一遍就可以求出最优解,大部分情况下这是不可行的。 贪心算法和动态规划本质上是对子问题树的一种修剪,两种算法要求问题都具有 的一个性质就是子问题最优性(组成最优解的每一个子问题的解,对于这个子问 题本身肯定也是最优的)。动态规划方法代表了这一类问题的一般解法,我们自 底向上构造子问题的解,对每一个子树的根,求出下面每一个叶子的值,并且以 其中的最优值作为自身的值,其它的值舍弃。而贪心算法是动态规划方法的一个 特例,可以证明每一个子树的根的值不取决于下面叶子的值,而只取决于当前问 题的状况。换句话说,不需要知道一个节点所有子树的情况,就可以求出这个节 点的值。由于贪心算法的这个特性,它对解空间树的遍历不需要自底向上,而只 需要自根开始,选择最优的路,一直走到底就可以了。

贪心算法原理及应用

贪心算法原理及应用

贪心算法原理及应用随着人工智能技术的不断发展,算法的种类也越来越多,其中贪心算法作为一种最基础的算法,也在不断优化和升级。

本文将简要介绍贪心算法原理及其应用,探讨贪心算法的优劣和适用场景。

一、贪心算法原理贪心算法是一种常见的优化算法,它的基本思想是:在每一步选择中都采取当前状态下最优的选择,从而希望最终得到全局最优的解。

贪心算法在每一步选择中都依赖于以前的选择结果,但不依赖于将来的选择结果。

这种贪心选择性质是该算法能达到最终全局最优解的保证。

然而,即使每个局部最优的选择都是正确的,但最终的全局最优解并不一定会得到,因此贪心算法不一定能得到全局最优解,但是在实际问题中,贪心算法通常可以得到非常接近最优解的结果。

二、贪心算法应用1.最小生成树最小生成树是图论中的一个经典算法问题,它可以用贪心算法来解决。

在给定一个带权无向图时,我们需要找到一棵生成树,使得生成树所有边的权值之和最小。

Prim算法和Kruskal算法都是基于这一思想建立的。

2.背包问题背包问题是一种经典的动态规划问题,也可以用贪心算法来解决。

在背包问题中,我们需要找到一种最佳的方案,使得放入背包的物品的总价值最大。

3.活动安排在一组活动中,每个活动都有一个开始时间和结束时间。

如何安排这些活动,使得可以安排的最多?可以用贪心算法进行解决。

三、贪心算法的优劣1.优点优点是:简单,易于实现;对于一些问题可以快速得到答案。

2.缺点缺点是:贪心算法不能保证得到全局最优解,只能得到最终结果接近最优解的结果。

在一些问题中会出现无解的情况。

此外,贪心算法需要根据实际问题进行调整,否则可能会得到错误的答案。

3.适用场景对于一些特殊的问题,贪心算法通常可以得到非常好的效果。

例如上文提到的最小生成树、背包问题和活动安排等等。

在这些问题中,贪心算法可以得到接近最优解的结果。

但是,在一些问题中,贪心算法的结果会偏离真实结果。

四、结语贪心算法是一种简单而实用的算法,它在很多实际问题中都有广泛的应用。

贪心算法的概念和适用条件 -回复

贪心算法的概念和适用条件 -回复

贪心算法的概念和适用条件-回复什么是贪心算法?贪心算法(Greedy Algorithm)是一种以局部最优解为导向的算法思想,通过每一步选择当前状态下的最佳操作来达到整体最优解的目标。

贪心算法的核心思想是每次都做出当前看来最优的选择,以期望能够达到整体的最优解。

贪心算法通常用于一些问题中,即每一步的选择只依赖于当前状态,而不考虑将来可能出现的情况。

贪心算法的适用条件:1. 贪心选择性质:贪心算法每一步都选择一个当前的最优解,此处的“最优”指的是局部最优。

这种最优选择可以确保问题能够被拆解,并且进行下一步求解。

2. 最优子结构性质:当问题的整体最优解能够通过局部最优解得到时,可以采用贪心算法求解。

这种情况下,问题的最优解可以由子问题的最优解推导出来。

3. 无后效性:贪心算法选择某一步操作时,只考虑当前状态,不会改变以前的操作,并且不关心未来的操作。

这种无后效性使得贪心算法在实际应用中操作简单、效率高。

贪心算法的基本步骤:1. 确定问题的局部最优解:贪心算法的核心是每一步都选择在当前情况下的最优解。

因此,需要确定问题如何拆解以及如何进行局部最优选择。

2. 定义问题的子问题:根据问题的最优子结构性质,将问题拆解为较小规模的子问题。

子问题应该是原问题的一个更小、更简单的实例。

3. 定义贪心选择策略:根据问题的特性,确定当前步骤下的最优选择策略。

这个选择应该是局部最优的,可以在不考虑子问题和整体未来状态的情况下得出。

4. 重复执行步骤2和3,直至求解出全局最优解。

贪心算法的优缺点:贪心算法具有简单易懂、快速高效的特点,适用于许多实际问题。

它可以避免穷举所有可能性,节省了计算时间。

此外,贪心算法常常能够找到近似最优解,尽管不一定能够保证全局最优解。

在实际问题中,近似最优解也往往可以满足实际需求。

然而,贪心算法并非适用于所有问题。

由于贪心算法只考虑当前状态的最优选择,而不考虑未来的影响,因此可能会导致局部最优解与全局最优解不一致。

贪心算法和回溯算法

贪心算法和回溯算法

贪⼼算法和回溯算法⼀.贪⼼算法 1.贪⼼算法是把⼀个复杂的问题分解为⼀个较为简单的局部最优选择,每⼀步选择都是对当前解的⼀个扩展,直到获取问题的完整。

贪⼼算法的典型运⽤是求解最优化问题,⽽且对许多问题都能得到整体最优解。

(这⾥得到的结不⼀定是最优解,但⼀定是最优解的⼗分接近的解) 2.可以使⽤贪⼼算法的要具有两个重要的性质:最优⼦结构和贪⼼选择性质 (1)最优⼦结构:在这⾥就不再说了,要看的请到上⼀章的动态规划⾥看。

(2)贪⼼选择性质:指问题的整体最优解可以通过⼀系列的局部最优的选择得到。

3.贪⼼算法和动态规划的主要区别: (1)动态规划:只要求出相关的⼦问题的解后才能做出选择 (2)贪⼼算法:仅当前的状态下做出最好的选择,即局部最优选,产⽣再去作出这样选择后产⽣的相关⼦问题的解。

4.贪⼼算法通常被使⽤来求解最优的问题,从某初始化的状态出发,根据但前的局部最优策略以满⾜约束⽅程为条件,以是⽬标函数增长最快(最慢)为准则,在候选集合进⾏⼀系列的选择,以便尽快的构成问题的可⾏解。

5.贪⼼算法的⼀般步骤: Greedy(C) //C是问题的输⼊集合,即候选集合 { S={}; //初始化解集合为空集 while(not solution(S)) //集合S没有构成问题的⼀个解 { x=select(C); //在候选集合C中做贪⼼选择 if feasible(S,x) //判断集合S中加⼊x后的解是否可⾏ { S=S+{X}; } C=C-{x}; //不管可不可⾏,都要从候选集中C删除x } return S; }⼆.回溯算法 1.回溯算法就是⼀种有组织的系统最优化搜索技术,可以看作蛮⼒法穷举搜索的改进。

回溯法常常可以避免搜索所有可能的解,所以它是⽤求解组织数量较⼤的问题。

(为什么?后⾯会解释) 2.⾸先我们先了解⼀下⼀个基本概念“解空间树”:问题的解空间⼀般使⽤解空间树的⽅式来组织,树的根节点位于第1层,表⽰搜索的初始状态,依次向下排列。

0021算法笔记——【贪心算法】贪心算法与精彩活动安排问题

0021算法笔记——【贪心算法】贪心算法与精彩活动安排问题

0021算法笔记——【贪心算法】贪心算法与活动安排问题1、贪心算法(1)原理:在对问题求解时,总是做出在当前看来是最好的选择。

也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。

贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。

(2)特性:贪心算法采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解,虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪婪法不要回溯。

能够用贪心算法求解的问题一般具有两个重要特性:贪心选择性质和最优子结构性质。

1)贪心选择性质所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。

这是贪心算法可行的第一个基本要素。

贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。

对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。

证明的大致过程为:首先考察问题的一个整体最优解,并证明可修改这个最优解,使其以贪心选择开始。

做了贪心选择后,原问题简化为规模更小的类似子问题。

然后用数学归纳法证明通过每一步做贪心选择,最终可得到问题的整体最优解。

其中,证明贪心选择后的问题简化为规模更小的类似子问题的关键在于利用该问题的最优子结构性质。

2)最优子结构性质当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。

(3)贪心算法与动态规划算法的差异:动态规划和贪心算法都是一种递推算法,均有最优子结构性质,通过局部最优解来推导全局最优解。

两者之间的区别在于:贪心算法中作出的每步贪心决策都无法改变,因为贪心策略是由上一步的最优解推导下一步的最优解,而上一部之前的最优解则不作保留,贪心算法每一步的最优解一定包含上一步的最优解。

易语言 贪心算法

易语言 贪心算法

易语言贪心算法贪心算法(Greedy Algorithm)是一种常用的算法思想,它在每一步选择中都采取当前状态下最优的选择,从而希望最终能够获得全局最优解。

本文将介绍贪心算法的基本概念、特点以及应用,并通过一些具体的例子来进一步说明其实现过程和效果。

一、贪心算法的基本概念贪心算法是一种基于贪心策略的求解问题的方法。

它通过不断地做出局部最优选择,来达到全局最优的目标。

贪心算法的基本思想是每一步都选择当前状态下最优的解决方案,而不考虑其对后续步骤的影响。

这种局部最优的选择最终希望能够达到全局最优的结果。

二、贪心算法的特点1. 简单易实现:贪心算法的实现相对简单,不需要复杂的数据结构和算法;同时,贪心算法的思想也较为直观,容易理解和应用。

2. 效率高:相比于其他算法,贪心算法通常具有较高的执行效率,时间复杂度较低。

3. 局限性:贪心算法只关注当前的最优解,而不考虑其对后续步骤的影响,因此可能会得到次优解或不正确的解。

三、贪心算法的应用贪心算法在实际问题中有着广泛的应用。

下面通过几个具体的例子来说明贪心算法的应用过程。

1. 找零问题:假设有一些零钱,如1元、5元、10元、20元、50元和100元,要用最少的零钱凑出一个给定的金额。

贪心算法可以选择面值最大的零钱来凑,然后再选择次大面值的零钱,依次类推,直到凑出给定金额为止。

2. 区间覆盖问题:假设有一些区间,需要选择尽可能少的区间来覆盖给定的目标区间。

贪心算法可以选择结束时间最早的区间,然后排除与该区间重叠的其他区间,依次类推,直到覆盖所有目标区间。

3. 集合覆盖问题:假设有一些需要覆盖的元素,以及一些集合,每个集合包含一些元素,需要选择尽可能少的集合来覆盖所有元素。

贪心算法可以选择包含最多未覆盖元素的集合,然后排除已覆盖的元素,依次类推,直到覆盖所有元素。

四、贪心算法的实现过程贪心算法的实现过程通常包括以下几个步骤:1. 确定问题的最优子结构性质。

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

最优装载问题(贪心)

最优装载问题(贪心)

最优装载问题(贪⼼)⼀、实验内容运⽤贪⼼算法解决活动安排问题(或最优装载问题)使⽤贪⼼算法解决最优装载问题。

⼆、所⽤算法基本思想及复杂度分析1.算法基本思想贪⼼算法是指在对问题求解时,总是做出在当前看来是最好的选择。

也就是说,不从整体最优上加以考虑,它所做出的仅是在某种意义上的局部最优解。

⽤局部解构造全局解,即从问题的某⼀个初始解逐步逼近给定的⽬标,以尽可能快的求得更好的解。

当某个算法中的某⼀步不能再继续前进时,算法停⽌。

2.问题分析及算法设计问题分析:(1)给定n个古董,要把它们装到装载量为c的装载船上。

(2)⾸先需要对这n个古董进⾏质量从⼩到⼤的排序。

(3)然后每次都选择最轻的,接着再从剩下的n-1件物品中选择最轻的。

(4)重复第(3)步骤,直到当前载重量⼤于装载船的最⼤装载量,停⽌装载。

(5)此时得到最优的贪⼼⽅案,记录下装载的最⼤古董数。

算法设计:(1)算法策略:把n件物品从⼩到⼤排序,然后根据贪⼼策略尽可能多的选出前i个物品,直到不能装为⽌。

(2)特例:算法复杂度分析由最优装载问题的贪⼼选择性质和最优⼦结构性质,可知将这些古董按照其重量从⼩到⼤排序,所以算法所需的计算时间为O(nlogn)。

三、源程序核⼼代码及注释(截图)四、运⾏结果五、调试和运⾏程序过程中产⽣的问题及解决⽅法,实验总结(5⾏以上)这⾥的调试,没有什么⼤问题,单纯的依次⽐较,判断,从⽽得到结果。

这次实验让我对贪⼼算法有了更深刻的认识,其主要是从问题的初始解出发,按照当前最佳的选择,把问题归纳为更⼩的相似的⼦问题,并使⼦问题最优,再由⼦问题来推导出全局最优解。

贪⼼算法虽然求的是局部最优解,但往往许多问题的整体最优解都是通过⼀系列的局部最优解的选择来达到的,所以贪⼼算法不⼀定可以得到能推导出问题的最优解,但其解法是最优解的近似解。

懂得算法的原理,还需要多去练习才能更好的掌握其⽤法。

源码:#include<iostream>#include<algorithm>#define MAXN 1000005using namespace std;int w[MAXN];//每件古董的重量int main(){int c,n;//c:载重量,n古董数int sum = 0;//装⼊古董的数量int tmp = 0;//装⼊古董的重量cin >> c >> n;for(int i= 1; i <= n; ++i)cin >> w[i];sort(w+1,w+1+n);for(int i = 1; i <= n; ++i){tmp += w[i];if(tmp <= c)++sum;elsebreak;}cout << sum << endl;return 0;}。

贪心算法的图文讲解

贪心算法的图文讲解

总结
• 在对问题求解时,会选择当前看起来最有希望成功的边(任务) 。一旦做出决定,它就不会再重新考虑,也不会关心后面会引发 什么情况。也就是说,不从整体最优上加以考虑,它所做出的是 在某种意义上的局部最优解。 • 贪心算法是一种能够得到某种度量意义下的最优解的分级处理方 法,通过一系列的选择来得到一个问题的解,而它所做的每一次 选择都是当前状态下某种意义的最好选择,即贪心选择。即希望 通过问题的局部最优解来求出整个问题的最优解。这种策略是一 种很简洁的方法,对许多问题它能产生整体最优解,但不能保证 总是有效,因为它不是对所有问题都能得到整体最优解,只能说 其解必然是最优解的很好近似值
对于这个问题我们有以下几种情况:设加油次数为k,每个加油 站间距离为a[i];i=0,1,2,3……n (1)始点到终点的距离小于N,则加油次数k=0; (2)始点到终点的距离大于N时: A 加油站间的距离相等,即a[i]=a[j]=L=N,则加油次数最少k=n ; B 加油站间的距离相等,即a[i]=a[j]=L>N,则不可能到达终点; C 加油站间的距离相等,即a[i]=a[j]=L<N,则加油次数 k=n/N(n%N==0)或k=[n/N]+1(n%N!=0); D 加油站间的距离不相等,即a[i]!=a[j],则加油次数k通过贪心 算法求解。

• • 贪心的基本思想
• 用局部解构造全局解,即从问题的某一个初始解逐步逼 近给定的目标,以尽可能快地求得更好的解。当某个算 法中的某一步不能再继续前进时,算法停止。贪心算法 思想的本质就是分处理 出一个最好的方案。 • 利用贪心策略解题,需要解决两个问题: • (1)该题是否适合于用贪心策略求解; • (2)如何选择贪心标准,以得到问题的最优/较优解。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

贪心算法详解贪心算法思想:顾名思义,贪心算法总是作出在当前看来最好的选择。

也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。

当然,希望贪心算法得到的最终结果也是整体最优的。

虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。

如单源最短路经问题,最小生成树问题等。

在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。

贪心算法的基本要素:1.贪心选择性质。

所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。

这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。

动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。

对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。

2. 当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。

问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。

贪心算法的基本思路:从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。

当达到算法中的某一步不能再继续前进时,算法停止。

该算法存在问题:1. 不能保证求得的最后解是最佳的;2. 不能用来求最大或最小解问题;3. 只能求满足某些约束条件的可行解的范围。

实现该算法的过程:从问题的某一初始解出发;while 能朝给定总目标前进一步do求出可行解的一个解元素;由所有解元素组合成问题的一个可行解;用背包问题来介绍贪心算法:背包问题:有一个背包,背包容量是M=150。

有7个物品,物品可以分割成任意大小。

要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。

物品A B C D E F G重量35 30 60 50 40 10 25价值10 40 30 50 35 40 30分析如下目标函数:∑pi最大约束条件是装入的物品总重量不超过背包容量:∑wi<=M( M=150)。

(1)根据贪心的策略,每次挑选价值最大的物品装入背包,得到的结果是否最优?(2)每次挑选所占重量最小的物品装入是否能得到最优解?(3)每次选取单位重量价值最大的物品,成为解本题的策略。

值得注意的是,贪心算法并不是完全不可以使用,贪心策略一旦经过证明成立后,它就是一种高效的算法。

贪心算法还是很常见的算法之一,这是由于它简单易行,构造贪心策略不是很困难。

可惜的是,它需要证明后才能真正运用到题目的算法中。

一般来说,贪心算法的证明围绕着:整个问题的最优解一定由在贪心策略中存在的子问题的最优解得来的。

对于背包问题中的3种贪心策略,都是无法成立(无法被证明)的,解释如下:贪心策略:选取价值最大者。

反例:W=30物品:A B C重量:28 12 12价值:30 20 20根据策略,首先选取物品A,接下来就无法再选取了,可是,选取B、C则更好。

(2)贪心策略:选取重量最小。

它的反例与第一种策略的反例差不多。

(3)贪心策略:选取单位重量价值最大的物品。

反例:W=30物品:A B C重量:28 20 10价值:28 20 10根据策略,三种物品单位重量价值一样,程序无法依据现有策略作出判断,如果选择A,则答案错误。

但是果在条件中加一句当遇见单位价值相同的时候,优先装重量小的,这样的问题就可以解决.所以需要说明的是,贪心算法可以与随机化算法一起使用,具体的例子就不再多举了。

(因为这一类算法普及性不高,而且技术含量是非常高的,需要通过一些反例确定随机的对象是什么,随机程度如何,但也是不能保证完全正确,只能是极大的几率正确)。

下面我们看一些简单例题。

例24:在N行M列的正整数矩阵中,要求从每行中选出1个数,使得选出的总共N个数的和最大。

分析:要使总和最大,则每个数要尽可能大,自然应该选每行中最大的那个数。

因此,我们设计出如下算法:读入N, M,矩阵数据;Total := 0;For I := 1 to N do begin {对N行进行选择}选择第I行最大的数,记为K;Total := Total + K;End;输出最大总和Total;从上例中我们可以看出,和递推法相仿,贪心法也是从问题的某一个初始解出发,向给定的目标递推。

但不同的是,推进的每一步不是依据某一固定的递推式,而是做一个局部的最优选择,即贪心选择(在例中,这种贪心选择表现为选择一行中的最大整数),这样,不断的将问题归纳为若干相似的子问题,最终产生出一个全局最优解。

特别注意的是是,局部贪心的选择是否可以得出全局最优是能否采用贪心法的关键所在。

对于能否使用贪心策略,应从理论上予以证明。

下面我们看看另一个问题。

例25:部分背包问题给定一个最大载重量为M的卡车和N种食品,有食盐,白糖,大米等。

已知第i种食品的最多拥有W i公斤,其商品价值为V i元/公斤,编程确定一个装货方案,使得装入卡车中的所有物品总价值最大。

分析:因为每一个物品都可以分割成单位块,单位块的利益越大显然总收益越大,所以它局部最优满足全局最优,可以用贪心法解答,方法如下:先将单位块收益按从大到小进行排列,然后用循环从单位块收益最大的取起,直到不能取为止便得到了最优解。

因此我们非常容易设计出如下算法:问题初始化;{读入数据}按V i从大到小将商品排序;I := 1;repeatif M = 0 then Break; {如果卡车满载则跳出循环}M := M - W i;if M >= 0 then 将第I种商品全部装入卡车else将(M + W i)重量的物品I装入卡车;I := I + 1; {选择下一种商品}until (M <= 0) OR (I >= N)在解决上述问题的过程中,首先根据题设条件,找到了贪心选择标准(V i),并依据这个标准直接逐步去求最优解,这种解题策略被称为贪心法。

Program Exam25;Const Finp='Input.Txt';Fout='Output.Txt';Var N,M :Longint;S :Real;P,W :Array[1..100] Of Integer; Procedure Init; {输出}Var I :Integer;BeginAssign(Input,Finp); Reset(Input);Readln(M,N);For I:=1 To N Do Readln(W[I],P[I]);Close(Input);End;Procedure Sort(L,R:Integer); {按收益值从大到小排序}Var I,J,Y :Integer;X :Real;BeginI:=L; J:=R;X:=P[(L+R) Div 2]/W[(L+R) Div 2];RepeatWhile (I<R)And(P[I]/W[I]>=X) Do Inc(I);While (P[J]/W[J]<=X)And(J>L) Do Dec(J);If I<=J ThenBeginY:=P[I]; P[I]:=P[J]; P[J]:=Y;Y:=W[I]; W[I]:=W[J]; W[J]:=Y;Inc(I); Dec(J);End;Until I>J;If I<R Then Sort(I,R);If L<J Then Sort(L,J);End;Procedure Work;Var I :Integer;BeginSort(1,N);For I:=1 To N DoIf M>=W[I] Then {如果全部可取,则全取}BeginS:=S+P[I]; M:=M-W[I];EndElse {否则取一部分}BeginS:=S+M*(P[I]/W[I]); Break;End;End;Procedure Out; {输出}BeginAssign(Output,Fout); Rewrite(Output);Writeln(S:0:0);Close(Output);End;Begin {主程序}Init;Work;Out;End.因此,利用贪心策略解题,需要解决两个问题:首先,确定问题是否能用贪心策略求解;一般来说,适用于贪心策略求解的问题具有以下特点:①可通过局部的贪心选择来达到问题的全局最优解。

运用贪心策略解题,一般来说需要一步步的进行多次的贪心选择。

在经过一次贪心选择之后,原问题将变成一个相似的,但规模更小的问题,而后的每一步都是当前看似最佳的选择,且每一个选择都仅做一次。

②原问题的最优解包含子问题的最优解,即问题具有最优子结构的性质。

在背包问题中,第一次选择单位质量最大的货物,它是第一个子问题的最优解,第二次选择剩下的货物中单位重量价值最大的货物,同样是第二个子问题的最优解,依次类推。

其次,如何选择一个贪心标准?正确的贪心标准可以得到问题的最优解,在确定采用贪心策略解决问题时,不能随意的判断贪心标准是否正确,尤其不要被表面上看似正确的贪心标准所迷惑。

在得出贪心标准之后应给予严格的数学证明。

下面来看看0-1背包问题。

给定一个最大载重量为M的卡车和N种动物。

已知第i种动物的重量为W i,其最大价值为V i,设定M,W i,V i均为整数,编程确定一个装货方案,使得装入卡车中的所有动物总价值最大。

分析:对于N种动物,要么被装,要么不装,也就是说在满足卡车载重的条件下,如何选择动物,使得动物价值最大的问题。

即确定一组X1,X2,…,Xn, Xi∈{0,1}f(x)=max(∑X i*V i) 其中,∑(X i*W i)≦W从直观上来看,我们可以按照上例一样选择那些价值大,而重量轻的动物。

也就是可以按价值质量比(V i/W i)的大小来进行选择。

可以看出,每做一次选择,都是从剩下的动物中选择那些V i/W i最大的,这种局部最优的选择是否能满足全局最优呢?我们来看看一个简单的例子:设N=3,卡车最大载重量是100,三种动物A、B、C的重量分别是40,50,70,其对应的总价值分别是80、100、150。

情况A:按照上述思路,三种动物的V i/W i分别为2,2,2.14。

显然,我们首先选择动物C,得到价值150,然后任意选择A或B,由于卡车最大载重为100,因此卡车不能装载其他动物。

情况B:不按上述约束条件,直接选择A和B。

可以得到价值80+100=180,卡车装载的重量为40+50=90。

没有超过卡车的实际载重,因此也是一种可行解,显然,这种解比上一种解要优化。

相关文档
最新文档