贪心算法详解
《贪心算法》课件
![《贪心算法》课件](https://img.taocdn.com/s3/m/c6303998ac51f01dc281e53a580216fc700a53c6.png)
最小生成树
在给定的图上找到一棵包含 了所有顶点且边权值最小的 树。
最短路径
找到两个顶点之间的最短路 径。
贪心算法与动态规划的比较
贪心算法和动态规划都是解决最优化问题的方法,但贪心算法一般只考虑局 部最优解,而动态规划则利用全局最优解来求解。
贪心算法的优缺点
《贪心算法》PPT课件
欢迎大家来到《贪心算法》的PPT课件。在本次课程中,我们将探索算法和贪 心算法的概述,并深入了解贪心算法的定义、原理、特点以及应用场景。
算法和贪心算法的概述
算法是解决问题的步骤和规则的集合。贪心算法是一种将每一步操作中所做的最优选择合并起来,来解决整个 问题的算法。
贪心算法定义及原理
优点
• 简单易实现 • 在某些问题上能够获得最优解 • 计算效率高
缺点
• 并不一定能得到全局最优解 • 对问题的要求较高 • 局部最优解不能导致最终最优解
贪心
选择最多的相互兼容活动。
2
硬币找零问题
给定一些硬币面额,求找零时所需的最少硬币数。
3
区间调度问题
找到最多的不重叠区间。
贪心算法是一种每次都做出当前看起来最佳选择的算法。它基于局部最优解,并希望通过一系列局部最优解来 达到全局最优解。
贪心算法的特点
1 贪心选择性
每一步都采取当前最优的 选择。
2 无后效性
当前的选择不会影响以后 的选择。
3 子问题最优解
通过求解子问题的最优解 来构建全局最优解。
贪心算法的应用场景
霍夫曼编码
贪心算法实例分析
![贪心算法实例分析](https://img.taocdn.com/s3/m/f609c4bdfbb069dc5022aaea998fcc22bcd143ff.png)
贪心算法实例分析贪心算法,是一种常见的解决问题的方法,尤其在最优化问题中得到了广泛的应用。
简单来说,贪心算法是建立在选取局部最优解的基础上,通过不断的贪心选择,达到全局最优解的目的。
本文将通过两个实例,介绍使用贪心算法的思路和实现方法。
实例一:零钱兑换问题假设有 n 种不同面值的硬币,每种面值的硬币数量无限,现在需要兑换一个目标值amount 元,求兑换所需的最少硬币数。
例如:有2元、5元、10元、20元、50元、100元六种面值的硬币,需要兑换52元,则兑换最少需要三枚硬币:两枚20元硬币和一枚10元硬币。
思路分析:对于这个问题,我们可以把它看成选择一定数量的硬币使其面值之和等于 amount,且硬币数量最少。
为了使硬币数量最少,我们每次都选取当前面值最大并且小于剩余兑换金额的硬币。
这相当于在每个阶段选择局部最优解,最终得到的就是全局最优解。
实现方法:1. 排序:将硬币面额按从大到小的顺序排列。
2. 贪心选择:从面额最大的硬币开始选取,直到兑换金额为 0 或全部面额都被选择过。
代码示例:```pythondef coinChange(coins, amount):coins.sort(reverse=True) # 排序res = 0for coin in coins:while amount >= coin: # 贪心选择amount -= coinres += 1return res if amount == 0 else -1```实例二:区间调度问题假设有 n 个区间 [start, end],现在需要选出最多的区间,使得它们没有重叠。
例如:有四个区间[1,3]、[2,4]、[3,6]、[5,7],选出的最多区间数是 3,即选出[1,3]、[3,6]、[5,7]这三个区间。
思路分析:这个问题可以看成排序和贪心选择问题的复合。
首先,我们将所有区间按照 end 非递减的顺序排序。
然后从第一个区间开始,依次选取与当前区间不重叠且start 大于等于当前区间的所有区间,直到所有区间都被检查完。
贪心算法详解
![贪心算法详解](https://img.taocdn.com/s3/m/4e49b39571fe910ef12df83c.png)
贪心算法详解贪心算法思想:顾名思义,贪心算法总是作出在当前看来最好的选择。
也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。
当然,希望贪心算法得到的最终结果也是整体最优的。
虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。
如单源最短路经问题,最小生成树问题等。
在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。
贪心算法的基本要素: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)。
c语言贪心算法
![c语言贪心算法](https://img.taocdn.com/s3/m/5fd19b65492fb4daa58da0116c175f0e7cd11980.png)
c语言贪心算法一、引言贪心算法是一种在每一步选择中都采取当前情况下的最佳(或最优)选择的算法,它希望通过做出局部最优选择来获得全局最优解。
在C语言中,贪心算法是一种常用的优化方法,可以应用于各种问题领域,如资源分配、背包问题、图着色等。
二、基本概念贪心算法的基本思想是,在每一步选择中,总是做出在当前看来最好的选择,期望最终能得到最优解。
贪心算法并不保证得到最优解,但在很多情况下能得到满意的结果。
在C语言中,可以使用结构体、数组等数据结构来实现贪心算法。
三、应用示例以下是一个简单的贪心算法示例,用于解决公交线路规划问题。
假设有n个公交站点,我们希望通过贪心算法来规划一条公交线路,使得线路长度最短。
```c#include<stdio.h>#include<stdlib.h>typedefstruct{intstart;//起点站编号intend;//终点站编号intdistance;//站点之间的距离}Station;//贪心算法选择站点intgreedy_route(Station*stations,intn){inti,j;intbest_distance=stations[0].distance;//初始化起点站到终点的距离为最小距离intbest_route=stations[0].start;//初始化最佳路线为起点站for(i=1;i<n;i++){//考虑所有可能的路线组合,找出当前距离最短的路线和最近的站点作为下一个站点for(j=0;j<i;j++){if(stations[j].distance+stations[i].distance<best_distance){best_distance=stations[j].distance+stations[i].distance;best_route=stations[i].end;//更新最佳路线为最近的站点}}//将当前站点加入路线中stations[i].start=best_route;//将终点站编号赋值给当前站点起始站编号}returnbest_route;//返回最终的公交线路编号}```四、总结通过以上示例,我们可以看到贪心算法在公交线路规划问题中的应用。
0021算法笔记——【贪心算法】贪心算法与精彩活动安排问题
![0021算法笔记——【贪心算法】贪心算法与精彩活动安排问题](https://img.taocdn.com/s3/m/5e335c29fc4ffe473368ab8a.png)
0021算法笔记——【贪心算法】贪心算法与活动安排问题1、贪心算法(1)原理:在对问题求解时,总是做出在当前看来是最好的选择。
也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。
贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。
(2)特性:贪心算法采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解,虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪婪法不要回溯。
能够用贪心算法求解的问题一般具有两个重要特性:贪心选择性质和最优子结构性质。
1)贪心选择性质所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。
这是贪心算法可行的第一个基本要素。
贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。
对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。
证明的大致过程为:首先考察问题的一个整体最优解,并证明可修改这个最优解,使其以贪心选择开始。
做了贪心选择后,原问题简化为规模更小的类似子问题。
然后用数学归纳法证明通过每一步做贪心选择,最终可得到问题的整体最优解。
其中,证明贪心选择后的问题简化为规模更小的类似子问题的关键在于利用该问题的最优子结构性质。
2)最优子结构性质当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。
(3)贪心算法与动态规划算法的差异:动态规划和贪心算法都是一种递推算法,均有最优子结构性质,通过局部最优解来推导全局最优解。
两者之间的区别在于:贪心算法中作出的每步贪心决策都无法改变,因为贪心策略是由上一步的最优解推导下一步的最优解,而上一部之前的最优解则不作保留,贪心算法每一步的最优解一定包含上一步的最优解。
易语言 贪心算法
![易语言 贪心算法](https://img.taocdn.com/s3/m/15b5aad15ff7ba0d4a7302768e9951e79b896935.png)
易语言贪心算法贪心算法(Greedy Algorithm)是一种常用的算法思想,它在每一步选择中都采取当前状态下最优的选择,从而希望最终能够获得全局最优解。
本文将介绍贪心算法的基本概念、特点以及应用,并通过一些具体的例子来进一步说明其实现过程和效果。
一、贪心算法的基本概念贪心算法是一种基于贪心策略的求解问题的方法。
它通过不断地做出局部最优选择,来达到全局最优的目标。
贪心算法的基本思想是每一步都选择当前状态下最优的解决方案,而不考虑其对后续步骤的影响。
这种局部最优的选择最终希望能够达到全局最优的结果。
二、贪心算法的特点1. 简单易实现:贪心算法的实现相对简单,不需要复杂的数据结构和算法;同时,贪心算法的思想也较为直观,容易理解和应用。
2. 效率高:相比于其他算法,贪心算法通常具有较高的执行效率,时间复杂度较低。
3. 局限性:贪心算法只关注当前的最优解,而不考虑其对后续步骤的影响,因此可能会得到次优解或不正确的解。
三、贪心算法的应用贪心算法在实际问题中有着广泛的应用。
下面通过几个具体的例子来说明贪心算法的应用过程。
1. 找零问题:假设有一些零钱,如1元、5元、10元、20元、50元和100元,要用最少的零钱凑出一个给定的金额。
贪心算法可以选择面值最大的零钱来凑,然后再选择次大面值的零钱,依次类推,直到凑出给定金额为止。
2. 区间覆盖问题:假设有一些区间,需要选择尽可能少的区间来覆盖给定的目标区间。
贪心算法可以选择结束时间最早的区间,然后排除与该区间重叠的其他区间,依次类推,直到覆盖所有目标区间。
3. 集合覆盖问题:假设有一些需要覆盖的元素,以及一些集合,每个集合包含一些元素,需要选择尽可能少的集合来覆盖所有元素。
贪心算法可以选择包含最多未覆盖元素的集合,然后排除已覆盖的元素,依次类推,直到覆盖所有元素。
四、贪心算法的实现过程贪心算法的实现过程通常包括以下几个步骤:1. 确定问题的最优子结构性质。
2. 建立数学模型来描述问题。
Python中的贪心算法
![Python中的贪心算法](https://img.taocdn.com/s3/m/2f0c6f130166f5335a8102d276a20029bc646341.png)
Python中的贪心算法贪心算法是一种简单而有效的算法,通常用于对最优解进行近似求解。
它通过不断地做出最合适的选择来达到全局最优解的近似,而不是对整个问题进行全面的评估。
贪心算法的核心思想是:在每一步中都选择当前最优的解决方案,然后再尝试将其与其他已选择的解决方案组合起来,得到更优的解决方案。
这种方法通常很容易实现,并且可以得到符合实际使用的结果。
但是,贪心算法并不总是能够得到全局最优解,有时会出现选择局部最优解而导致全局最优解无法实现的情况。
贪心算法的应用范围非常广泛,它可用于优化问题、图形问题、字符串问题等各种领域,并且还可以与其他算法组合使用。
例如,贪心算法可以与动态规划算法结合使用,以加快计算速度并得到更好的结果。
贪心算法通常有以下几个基本步骤:1.确定问题的最优子结构贪心算法的第一步是确定问题是否具有最优子结构。
它意味着,在问题的任何阶段,我们都可以通过选择当前最优的子问题解决方案来获得最优解决方案。
这样,我们就可以逐步地将问题分解为更小、更容易处理的子问题。
2.确定问题的贪心选择性质贪心算法的第二步是确定问题的贪心选择性质。
它意味着我们必须找到一种方法来使每一步的贪心选择都是局部最优的,并且能够达到全局最优解。
这通常需要我们对问题进行更深入的分析,以找到那些能够获得最高收益的解决方案。
3.构造整体最优解贪心算法的最后一步是使用贪心选择性质,逐步构造全局最优解。
这意味着我们在每一步中都要做出当前最优的选择,并将其添加到我们的解决方案中,直到得到整个问题的最优解。
下面我们将简单介绍一下贪心算法在不同领域的应用。
【1】组合优化问题在组合优化问题中,贪心算法通常用于通过寻找不断优化的局部解决方案来构建更好的全局解决方案。
例如,在背包问题中,我们要选择一些物品放入背包中,以使得它们的总重量不超过背包的容量,同时价值最高。
使用贪心算法,我们可以按照物品的价值密度(即物品的价值与重量之比)进行排序,然后选择具有最高价值密度的物品,以使得我们可以尽可能地放入更多的物品,并尽可能地增加总价值。
贪心算法Greedy
![贪心算法Greedy](https://img.taocdn.com/s3/m/2d722349854769eae009581b6bd97f192279bfb7.png)
void Knapsack(int n,float M,float v[],float w[],float x[]) {
Sort(n,v,w); int i; for (i=1;i<=n;i++) x[i]=0; float c=M; for (i=1;i<=n;i++) {
例如,设7个独立作业{1,2,3,4,5,6,7}由3台机 器M1,M2和M3加工处理。各作业所需的处理时 间分别为{2,14,4,16,6,5,3}。按算法greedy产生 的作业调度如下图所示,所需的加工时间为17。
例2.背包问题
0-1背包问题:
给定n种物品和一个背包。物品i的重量是Wi,其价值为 Vi,背包的容量为C。应如何选择装入背包的物品,使得 装入背包中物品的总价值最大?
在选择装入背包的物品时,对每种物品i只有2种选择,即装入 背包或不装入背包。不能将物品i装入背包多次,也不能只装入部 分的物品i。
背包问题:
template<class Type> void Loading(int x[], Type w[], Type c, int n) {
int *t = new int [n+1]; Sort(w, t, n); for (int i = 1; i <= n; i++) x[i] = 0; for (int i = 1; i <= n && w[t[i]] <= c; i++) {x[t[i]] = 1; c -= w[t[i]];} }
动态规划算法通常以自底向上的方式解各子问题,而 贪心算法则通常以自顶向下的方式进行,以迭代的方式 作出相继的贪心选择,每作一次贪心选择就将所求问题 简化为规模更小的子问题。
贪心算法的图文讲解
![贪心算法的图文讲解](https://img.taocdn.com/s3/m/67b5fe14844769eae009ed7a.png)
总结
• 在对问题求解时,会选择当前看起来最有希望成功的边(任务) 。一旦做出决定,它就不会再重新考虑,也不会关心后面会引发 什么情况。也就是说,不从整体最优上加以考虑,它所做出的是 在某种意义上的局部最优解。 • 贪心算法是一种能够得到某种度量意义下的最优解的分级处理方 法,通过一系列的选择来得到一个问题的解,而它所做的每一次 选择都是当前状态下某种意义的最好选择,即贪心选择。即希望 通过问题的局部最优解来求出整个问题的最优解。这种策略是一 种很简洁的方法,对许多问题它能产生整体最优解,但不能保证 总是有效,因为它不是对所有问题都能得到整体最优解,只能说 其解必然是最优解的很好近似值
对于这个问题我们有以下几种情况:设加油次数为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)如何选择贪心标准,以得到问题的最优/较优解。
c++贪心算法经典例题
![c++贪心算法经典例题](https://img.taocdn.com/s3/m/bf72c348f68a6529647d27284b73f242336c319c.png)
c++贪心算法经典例题和详解贪心算法(Greedy Algorithm)是一种优化问题解决方法,其基本思想是每一步都选择当前状态下的最优解,以期望达到全局最优解。
贪心算法的特点是每一步都要做出一个局部最优的选择,而这些局部最优选择最终构成了全局最优解。
下面是一个经典的贪心算法例题以及详解:例题:活动选择问题(Activity Selection Problem)假设有一个需要在同一时段使用同一个资源的活动集合,每个活动都有一个开始时间和结束时间。
设计一个算法,使得能够安排最多数量的互不相交的活动。
# 输入:-活动的开始时间数组`start[]`。
-活动的结束时间数组`end[]`。
# 输出:-选择的互不相交的活动的最大数量。
# 算法详解:1. 首先,将活动按照结束时间从小到大排序。
2. 选择第一个活动,并将其加入最终选择的集合中。
3. 对于剩下的活动,选择下一个结束时间最早且与前一个活动不冲突的活动。
4. 重复步骤3,直到所有活动都被选择。
```cpp#include <iostream>#include <algorithm>#include <vector>using namespace std;// 定义活动结构体struct Activity {int start, end;};// 比较函数,用于排序bool compareActivities(Activity a, Activity b) {return a.end < b.end;}// 贪心算法解决活动选择问题void activitySelection(vector<Activity>& activities) {// 按照结束时间排序sort(activities.begin(), activities.end(), compareActivities);// 第一个活动总是被选中cout << "Selected activity: (" << activities[0].start << ", " << activities[0].end << ")" << endl;// 选择其余活动int lastSelected = 0;for (int i = 1; i < activities.size(); i++) {// 如果当前活动的开始时间大于等于上一个选择的活动的结束时间,则选择该活动if (activities[i].start >= activities[lastSelected].end) {cout << "Selected activity: (" << activities[i].start << ", " << activities[i].end << ")" << endl;lastSelected = i;}}}int main() {vector<Activity> activities = {{1, 2}, {3, 4}, {0, 6}, {5, 7}, {8, 9}, {5, 9}};cout << "Activities before sorting:" << endl;for (const Activity& activity : activities) {cout << "(" << activity.start << ", " << activity.end << ") ";}cout << endl;activitySelection(activities);return 0;}```在这个例子中,我们首先定义了一个活动的结构体`Activity`,然后编写了一个比较函数`compareActivities` 用于排序。
第05章贪心算法
![第05章贪心算法](https://img.taocdn.com/s3/m/c07099e0a48da0116c175f0e7cd184254b351bc8.png)
第 05 章
贪 心
第05章 贪心算法
算
法
基本思想
通过作出在当前看来最优的选择(贪心选择),将原问题规模缩小,
第
05
如此反复,直至得到最终解。
章
贪心算法并非对所有问题都能得到整体最优解。
贪 心 算 法
贪心算法的基本要素
第 05 章
贪 心 算 法
1、贪心选择性质
所求问题的整体最优解可由一系列局部最优选择得到; 动态规划是由子问题的解得到当前问题的解;
心
叉树的权值为W’+(x+y)*(d-1),易见,若存在一个更优的二叉树,将x,y再替换回来也应是一棵
算
更优的二叉树;
法
证明:取x,y的父结点代替x,y结点,取x,y的权值和 作为其父结点的权值,得到的仍是一棵最优二叉树。
第
W’
W’
05
章
贪
心
XY
算
法
W = W’+x*d+y*d
W’+(x+y)*(d-1)
贪心算法的理论基础
第 05 章
贪 心 算 法
1、拟阵
拟阵定义为满足以下条件的有序对(S,I); S是一个非空有限集合;
I是S的具有某种遗传性质的独立子集的全集;一个集合是具有遗传性质的独立集合是指, 若一个集合具有某种性质,则其任意子集也具有该性质;
I满足交换性质,即若A∈I,B ∈I且|A|<|B|, 则存在某一元素x ∈B-A,使得A∪{x} ∈I;
哈夫曼算法的证明
最优子结构性质的证明
第
05
若叶结点x,y分别具有最小权值,而且是互为兄弟结点的最深的叶子结点,证明:取x,y的父结点
Python中的贪心算法优化技巧
![Python中的贪心算法优化技巧](https://img.taocdn.com/s3/m/23de007fa9956bec0975f46527d3240c8447a135.png)
Python中的贪心算法优化技巧贪心算法是一种基本的算法设计方法,它在许多实际问题中有很好的应用。
但是贪心算法有时候会产生局部最优解,而不是全局最优解,这就需要通过一些优化技巧来进行修正。
本文将从理解贪心算法、常见贪心算法及优化技巧、应用实例以及优缺点四个方面,深入探讨Python中的贪心算法优化技巧。
一、理解贪心算法贪心算法是一种基于贪心的算法,它根据当前状态做出最好的选择,并希望最终达到最优解。
这种算法往往需要满足贪心选择性质和最优子结构性质。
其中,贪心选择性质指的是在决策中每一步都要选择当前状态下的最佳决策,而不考虑过去或未来的决策,而最优子结构性质则意味着问题的最优解可以由其子问题的最优解组合而成。
二、常见贪心算法及优化技巧1.跳跃贪心算法又称作约束优化问题,即在某些限制条件下找到最大值或最小值,并且不管以后的影响,只针对当前选择问题的最优解。
例如在一个数列中,每个数最多只能选一次,找出其中的最大数之和。
跳跃贪心的优化主要在于对决策的遍历顺序和过程中尽量减少判断次数。
2.背包问题背包问题是动态规划中的经典问题,所谓背包问题,就是在有限的背包容量下,如何使得装入的物品具有最大的价值。
在使用贪心算法求解背包问题时,通常使用贪心选择策略是根据物品单位重量的价值进行排序,一次放入单位重量价值最大的物品。
然而在存在物品体积和性质或是背包容量有限的情况下,贪心算法并不能得到最优解。
此时,应用了动态规划和分支界限等算法,寻找更加优秀的解决方案。
3.活动安排问题活动安排问题是一种经典的贪心算法问题,假设已知n个活动的开始时间和结束时间,如何安排所有活动使得所有活动都能顺利进行而不冲突。
这个问题的贪心策略是,每次选择开始时间最早的活动作为下一个安排的活动。
而在优化上,可以采用缩小搜索范围、先排序后贪心等方法,以减少时间复杂度和空间复杂度。
4.多路归并问题多路归并问题是将多个有序序列合并成一个有序序列。
通常的贪心策略是在每次选取时都从n个队列中选出其中最小的元素进行合并。
贪心算法——精选推荐
![贪心算法——精选推荐](https://img.taocdn.com/s3/m/84ccd3bedc3383c4bb4cf7ec4afe04a1b071b0ef.png)
贪⼼算法⼀、基本概念所谓贪⼼算法是指,在对问题求解时,总是做出在当前看来是最好的选择。
也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。
贪⼼算法没有固定的算法框架,算法设计的关键是贪⼼策略的选择。
必须注意的是,贪⼼算法不是对所有问题都能得到整体最优解,选择的贪⼼策略必须具备⽆后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。
所以对所采⽤的贪⼼策略⼀定要仔细分析其是否满⾜⽆后效性。
⼆、贪⼼算法的基本思路1.建⽴数学模型来描述问题。
2.把求解的问题分成若⼲个⼦问题。
3.对每⼀⼦问题求解,得到⼦问题的局部最优解。
4.把⼦问题的解局部最优解合成原来解问题的⼀个解。
三、贪⼼算法适⽤的问题贪⼼策略适⽤的前提是:局部最优策略能导致产⽣全局最优解。
或者将贪⼼算法进⾏修改以求出全局最优解实际上,贪⼼算法适⽤的情况很少。
⼀般,对⼀个问题分析是否适⽤于贪⼼算法,可以先选择该问题下的⼏个实际数据进⾏分析,就可做出判断。
四、贪⼼算法的实现框架从问题的某⼀初始解出发;while (能朝给定总⽬标前进⼀步){利⽤可⾏的决策,求出可⾏解的⼀个解元素;}由所有解元素组合成问题的⼀个可⾏解;五、贪⼼策略的选择因为⽤贪⼼算法只能通过解局部最优解的策略来达到全局最优解,因此,⼀定要注意判断问题是否适合采⽤贪⼼算法策略,找到的解是否⼀定是问题的最优解。
六、例题分析下⾯是⼀个可以试⽤贪⼼算法解的题⽬,贪⼼解的确不错,可惜不是最优解。
[背包问题]有⼀个背包,背包容量是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)每次选取单位重量价值最⼤的物品,成为解本题的策略。
贪心算法的原理是
![贪心算法的原理是](https://img.taocdn.com/s3/m/35d6e3cad1d233d4b14e852458fb770bf78a3bd5.png)
贪心算法的原理是
贪心算法是一种求解最优问题的常用算法思想,其基本原理是在每一步选择中都采取当前状态下最优的选择,从而希望最终得到全局最优解。
贪心算法的主要特点是局部最优策略同时也是全局最优策略。
贪心算法通常包含以下步骤:
1. 确定问题的最优子结构:即问题的整体最优解可以通过一系列局部最优解来达到。
这是贪心算法的基础,也是保证贪心选择性质的关键。
2. 构造贪心选择:通过局部最优策略来构造每一步的最优解,不考虑前面步骤的选择是否能够达到全局最优。
3. 解决子问题:将子问题缩小,通过递归或迭代的方式求解。
4. 合并子问题的解:将子问题的解合并起来,形成原问题的解。
贪心算法的正确性依赖于贪心选择性质和最优子结构性质。
贪心选择性质指的是,通过局部最优解就可以推导出全局最优解。
最优子结构性质指的是,问题的整体最优解可以通过一系列局部最优解来达到。
贪心算法的应用广泛,常见的问题包括:
1. 找零钱问题:给定一些面额不同的硬币和一个总金额,如何用最少数量的硬币凑出总金额。
2. 区间调度问题:给定一些活动的开始时间和结束时间,如何安排活动使得参加的活动数量最多。
3. Huffman编码问题:如何用最短的编码长度来表示一个给定概率分布的字符集。
虽然贪心算法通常能够在很短的时间内找到一个解,但并不是所有问题都适合使用贪心算法。
贪心算法不能保证得到最优解,只能保证得到一个近似最优解。
因此,在使用贪心算法解决问题时需要根据具体问题的特性来判断是否适合使用贪心算法。
贪心算法的理解-概述说明以及解释
![贪心算法的理解-概述说明以及解释](https://img.taocdn.com/s3/m/e94a3054a66e58fafab069dc5022aaea998f41ad.png)
贪心算法的理解-概述说明以及解释1.引言1.1 概述概述部分的内容可以描述贪心算法的基本概念和作用。
贪心算法是一种常用的求解优化问题的算法思想,其核心思想是在每一步都选择当前最优解,从而希望最终达到全局最优解。
贪心算法通常适用于那些具有最优子结构特性和贪心选择性质的问题。
具体来说,贪心算法通常分为以下几个步骤:首先,根据问题的特性确定问题的目标函数或者判断问题的可行解的标准;其次,把原问题分解为若干个子问题,每次选择最优解作为当前问题的解;接着,对所选取的解进行判断,如果满足问题的约束条件,则放入解集中,否则舍弃;最后,递归或者迭代地处理下一个子问题,直到找出全局最优解。
贪心算法的应用非常广泛,它可以用来解决许多实际问题,比如最小生成树、最短路径、背包问题等。
贪心算法的优点在于简单、高效,其时间复杂度通常较低。
然而,贪心算法也有其局限性,它只关注当前的最优解而不考虑全局的最优解,因此在某些问题上可能会得到次优解甚至是错误的解。
综上所述,贪心算法是一种重要的优化算法思想,通过不断选择当前最优解来求解问题。
它的应用广泛,具有高效简单的特点,但也存在局限性。
在今后的发展中,我们可以对贪心算法进行改进,使其在更多的问题中发挥更强大的作用。
1.2 文章结构文章结构部分:本文分为引言、正文和结论三个部分。
引言部分主要概述了本文的主题——贪心算法,并介绍了文章的结构和目的。
正文部分将重点讲解贪心算法的定义、原理、应用场景以及优缺点。
首先,在2.1节中,我们将介绍什么是贪心算法。
贪心算法是一种在每一步选择中都选择当前情况下最好或最优的选择,以期望能够导致全局最优解的算法。
其次,在2.2节中,我们将详细解析贪心算法的原理。
贪心算法的核心思想是通过不断地做出局部最优选择,从而最终得到全局最优解。
我们将使用一些具体的示例来说明贪心算法的运作方式。
然后,在2.3节中,我们将探讨贪心算法的应用场景。
贪心算法在很多实际问题中都有广泛的应用,如任务调度、背包问题、最短路径等。
贪心算法理解贪心算法的基本原理和应用场景
![贪心算法理解贪心算法的基本原理和应用场景](https://img.taocdn.com/s3/m/452811765627a5e9856a561252d380eb629423fc.png)
贪心算法理解贪心算法的基本原理和应用场景贪心算法:理解贪心算法的基本原理和应用场景简介:贪心算法(Greedy Algorithm)是一种常用的算法设计和解决问题的方法。
它以一种贪婪的方式做出每一步的选择,希望最终能够达到整体上的最优解。
本文将介绍贪心算法的基本原理和常见应用场景。
一、贪心算法的基本原理贪心算法的基本原理是每次都做出当前最优的选择,希望最终能够达到整体上的最优解。
贪心算法的优点在于简单、高效,但由于它只关注当前最优解,因此可能无法得到全局最优解。
贪心算法的基本步骤如下:1. 将问题划分为若干子问题,每个子问题都有多个选择;2. 分析子问题的选择,以及每个选择的最优解;3. 根据每个子问题的最优解,做出当前最优的选择;4. 更新已做出选择的子问题集合;5. 重复步骤3和4,直到解决全部子问题。
二、贪心算法的应用场景1. 零钱兑换问题零钱兑换问题是指给定一个金额和一组零钱的面值,如何用最少数量的零钱找零。
贪心算法可以从面值最大的零钱开始,每次找零选择当前面值最大的零钱,直到达到目标金额。
2. 区间调度问题区间调度问题是指给定一组区间,如何选择最多数量的不相交区间。
贪心算法可以根据区间的结束时间进行排序,每次选择结束时间最早的区间,并排除与之重叠的其他区间。
3. 背包问题背包问题是指给定一组物品和一个固定容量的背包,如何选择物品放入背包,使得背包中物品的总价值最大。
贪心算法可以通过计算每个物品的单位价值(即物品的价值与重量的比值)来选择单位价值最高的物品放入背包。
4. 最短路径问题最短路径问题是指在一个有向图或无向图中,找到两个节点之间的最短路径。
贪心算法可以使用Dijkstra算法,每次选择离起始节点最近的未访问节点进行扩展,直到找到目标节点。
5. 活动选择问题活动选择问题是指在一组活动中,选出最大的互相兼容的活动子集合。
贪心算法可以根据活动的结束时间进行排序,每次选择结束时间最早的活动,并排除与之重叠的其他活动。
贪心算法详解
![贪心算法详解](https://img.taocdn.com/s3/m/899c9073f5335a8102d220cd.png)
第16章贪心算法理解贪心算法的概念zz掌握贪心算法的基本要素z理解贪心算法与动态规划算法的差异z通过范例学习贪心算法设计策略16116.1 活动安排问题z当一个问题具有最优子结构性质时,可用动态规划法求解,但有时用贪心算法求解会更加的简单有效。
z顾名思义,贪心算法总是作出在当前看来最好的选择。
也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。
当然,希望贪心算法得到的最终结果也是整体最优的。
虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。
单源最短路经问题,最小生成树问题等。
在些情解。
如单源最短路经问题,最小生成树问题等。
在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。
161z设有n个活动的集合E={1,2,…,n},其中每个活动都要求使16.1活动安排问题用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。
每个活动i都有一个要求使用该资源和个结束时间f 且s 如果选择了活动i 的起始时间s i 和一个结束时间f i ,且s i <f i 。
如果选择了活动i,则它在半开时间区间[s i , f i )内占用资源。
若区间[s i , f i )与区间[s , f 活动i与活动j是相容的。
也就是说,间[j ,j )不相交,则称活动与活动j是相容的也就是说,当s i ≥f j 或s j ≥f i 时,活动i与活动j相容。
z问题:选出最大的相容活动子集合。
16.1 活动安排问题161(用动态规划方法)z步骤1:分析最优解的结构特征—构造子问题空间:S ij={ a k∈S: f i≤s k<f k≤s j}S ij包含了所有与a i和a j相兼容的活动,并且与不迟于a i结束和不早于a j 开始的活动兼容。
此外,虚构活动a0和a n+1,其中f00, S n+1。
原=0,S=∞。
原问题即为寻找S0,n+1中最大兼容活动子集。
贪心算法(Greedy)
![贪心算法(Greedy)](https://img.taocdn.com/s3/m/4c1d000b76c66137ee0619f6.png)
例如, 例如,设7个独立作业{1,2,3,4,5,6,7}由3台 机器M1,M2和M3加工处理。各作业所需的处理时 间分别为{2,14,4,16,6,5,3}。按算法greedy greedy产生 greedy 的作业调度如下图所示,所需的加工时间为17。
约定,每个作业均可在任何一台机器上加工处理, 约定,每个作业均可在任何一台机器上加工处理,但未 完工前不允许中断处理。作业不能拆分成更小的子作业。 完工前不允许中断处理。作业不能拆分成更小的子作业。
采用最长处理时间作业优先 最长处理时间作业优先的贪心选择策略可以设计 最长处理时间作业优先 出解多机调度问题的较好的近似算法。 按此策略,当 n ≤ m时,只要将机器i的[0, ti]时间区间 分配给作业i即可,算法只需要O(1)时间。 i O(1) 当 n > m 时,首先将n个作业依其所需的处理时间从大 到小排序。然后依此顺序将作业分配给空闲的处理机。算 法所需的计算时间为O(nlogn)。
void Knapsack(int n,float M,float Knapsack(int v[],float w[],float x[]) { Sort(n,v,w); int i; for (i=1;i<=n;i++) x[i]=0; float c=M; for (i=1;i<=n;i++) { if (w[i]>c) break; x[i]=1; c-=w[i]; } if (i<=n) x[i]=c/w[i]; }
用贪心算法解背包问题的基本步骤:
首先计算每种物品单位重量的价值Vi/Wi,然后,依贪心 首先计算每种物品单位重量的价值Vi/Wi,然后,依贪心 选择策略,将尽可能多的单位重量价值最高 选择策略,将尽可能多的单位重量价值最高的物品装入背包。 单位重量价值最高的物品装入背包。 若将这种物品全部装入背包后,背包内的物品总重量未超过 C,则选择单位重量价值次高的物品并尽可能多地装入背包。 依此策略一直地进行下去,直到背包装满为止。 具体算法可描述如下页:
贪心算法及其应用
![贪心算法及其应用](https://img.taocdn.com/s3/m/639b8ddcf9c75fbfc77da26925c52cc58bd690eb.png)
贪心算法及其应用贪心算法,也叫贪心思想,是一种常用的算法思想,其核心思想就是在每一步选择中都选择当前状态下最优的选择,从而达到问题最优解。
贪心算法的优点是简单、高效,但是缺点也很明显,在某些情况下可能会得到次优解。
贪心算法的基本概念贪心算法是一种追求局部最优解的算法,也就是在每一步的选择中选择当前状态下最优的选择,从而使问题达到全局最优解。
贪心算法与分治算法、动态规划算法是并列的三大算法思想。
贪心算法的步骤:首先确定贪心的策略,然后根据贪心策略依次得到问题的最优解。
贪心算法的特点:每个决策只与当前状态有关,不依赖之前的决策或状态;每个子问题的最优解能够推导出全局最优解。
贪心算法的实现方式:从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的达到最优解。
贪心算法的应用贪心算法的应用很广泛,其中最常见的应用就是求解各种最优问题,例如:1. 找零钱问题。
例如要找 $n$ 元,有若干面值为 $v_1, v_2,\cdots, v_k$ 的硬币,试求出所有满足找零条件的方案中所含硬币数最少的那个方案。
2. 活动安排问题。
例如在 $n$ 个活动中选择一些举行,每个活动 $i$ 有一个开始时间 $s_i$ 和一个结束时间 $t_i$。
每个活动已经按结束时间的非降序排列。
如果选择了活动 $i$,则它的开始时间和结束时间分别是 $s_i$ 和 $t_i$,且有 $t_i \leq s_{i+1}$。
求最大的互不相交的活动子集并输出其中的一种方案。
3. 区间覆盖问题。
有 $n$ 个区间 $[l_i, r_i]$,设计一个算法,选择尽量少的区间,使得这些区间的并集能够完全覆盖 $[1, m]$,其中 $m$ 为一正整数。
以上三个问题都可以使用贪心算法来解决,其核心思想就是在每一步选择中都选择当前状态下最优的选择,从而达到问题最优解。
贪心算法的实例下面,我们以找零钱问题为例来阐述贪心算法的处理过程。
假设我们有若干面值为 $v_1, v_2, \cdots, v_k$ 的硬币,试求出所有满足找零条件的方案中所含硬币数最少的那个方案。
贪心算法求债权匹配问题
![贪心算法求债权匹配问题](https://img.taocdn.com/s3/m/d2f5f39cf424ccbff121dd36a32d7375a517c679.png)
贪心算法求解债权匹配问题1. 什么是贪心算法?贪心算法是一种常见的问题求解策略,它在每一步总是做出当前情况下看起来最优的选择,以期望最终达到全局最优解。
贪心算法通常不会进行全局的搜索,而是通过局部最优的选择逐步构建解决方案。
2. 债权匹配问题是什么?债权匹配问题是指在一组债权人(creditors)和债务人(debtors)之间,根据各自的债权和债务金额,找到一种最优的匹配方案,使得债权人和债务人之间的总债务差额最小。
3. 贪心算法求解债权匹配问题的思路贪心算法求解债权匹配问题的基本思路是按照债权人和债务人的债权和债务金额进行排序,然后逐个匹配债权人和债务人,每次选择债权金额最大的债权人和债务金额最大的债务人进行匹配,直到没有可匹配的债权人或债务人。
4. 贪心算法求解债权匹配问题的具体步骤以下是使用贪心算法求解债权匹配问题的具体步骤:步骤 1:根据债权人的债权金额进行降序排序。
步骤 2:根据债务人的债务金额进行降序排序。
步骤 3:初始化匹配结果为空。
步骤 4:依次遍历债权人和债务人列表,对于每个债权人和债务人:- 如果债权人的债权金额大于等于债务人的债务金额,则将债权人和债务人匹配,并更新债权人和债务人的债权和债务金额。
- 如果债权人的债权金额小于债务人的债务金额,则将债权人和债务人匹配,并更新债权人的债权金额为0,更新债务人的债务金额为债务人的债务金额减去债权人的债权金额。
步骤 5:返回匹配结果。
5. 贪心算法求解债权匹配问题的复杂度分析贪心算法求解债权匹配问题的时间复杂度主要取决于排序的时间复杂度,假设债权人和债务人的数量分别为 n 和 m ,则排序的时间复杂度为 O(nlogn + mlogm)。
遍历债权人和债务人列表的时间复杂度为 O(n + m)。
因此,贪心算法求解债权匹配问题的总时间复杂度为 O(nlogn + mlogm)。
结论贪心算法是一种常用的问题求解策略,可以应用于各种类型的问题。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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。
没有超过卡车的实际载重,因此也是一种可行解,显然,这种解比上一种解要优化。