常见的贪心算法问题

合集下载

经典贪心题

经典贪心题

贪心算法是一种在解决问题的过程中追求局部最优的算法,对于一个有多种属性的事物来说,贪心算法会优先满足某种条件,追求局部最优的同时希望达到整体最优的效果。

以下是一些经典的贪心算法问题:1. 背包问题:给定一组物品,每个物品都有自己的重量和价值,背包的总容量有限。

贪心算法需要选择物品以最大化背包中物品的总价值,同时不超过背包的总容量。

这种问题可以有多种变体,例如分数背包问题和完全背包问题。

2. 硬币找零问题:给定一组硬币的面值和数量,以及需要找零的金额。

贪心算法需要选择硬币以最小化找零的总数量。

这个问题可以通过从大到小排序硬币,并从最大面值的硬币开始选择,直到找零的金额达到所需的总金额。

3. 区间选点问题:给定一系列闭区间,每个闭区间都有一个起始点和结束点。

贪心算法需要选择尽量少的点,使得每个闭区间内至少有一个点被选中。

这个问题可以通过对结束点进行排序,并从左到右选择结束点,直到下一个要选择的结束点与上一个选择的结束点之间的距离大于当前选择的结束点与上一个选择的结束点之间的距离为止。

4. 区间覆盖问题:给定一系列闭区间,贪心算法需要选择尽量少的区间,使得所有区间都被覆盖。

这个问题可以通过对每个闭区间的左端点进行排序,并从左到右选择左端点,直到下一个要选择的左端点与上一个选择的左端点之间的距离大于当前选择的左端点与上一个选择的左端点之间的距离为止。

5. 排班问题:给定一组员工和他们的班次需求,以及一组工作日的日程安排。

贪心算法需要为员工分配班次,以最小化总工作时间并满足所有工作日的需求。

这个问题可以通过从可用的班次中选择最长的班次,并从左到右分配员工,直到所有员工都被分配到一个班次为止。

这些问题是贪心算法的经典示例,它们展示了贪心算法在解决优化问题中的广泛应用。

贪心算法练习题

贪心算法练习题

贪心算法1.喷水装置(一)描述现有一块草坪,长为20米,宽为2米,要在横中心线上放置半径为Ri的喷水装置,每个喷水装置的效果都会让以它为中心的半径为实数Ri(0<Ri<15)的圆被湿润,这有充足的喷水装置i(1<i<600)个,并且一定能把草坪全部湿润,你要做的是:选择尽量少的喷水装置,把整个草坪的全部湿润。

输入第一行m表示有m组测试数据每一组测试数据的第一行有一个整数数n,n表示共有n个喷水装置,随后的一行,有n个实数ri,ri表示该喷水装置能覆盖的圆的半径。

输出输出所用装置的个数样例输入252 3.2 4 4.5 6101 2 3 1 2 1.2 3 1.1 1 2样例输出25根据日常生活知道,选择半径越大的装置,所用的数目越少。

因此,可以先对半径排序,然后选择半径大的。

另外,当装置刚好喷到矩形的顶点时,数目最少。

此时只要装置的有效喷水距离的和不小于20时,输出此时的装置数目即可。

2.喷水装置(二)时间限制:3000 ms | 内存限制:65535 KB难度:4描述有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿。

请在给出的喷水装置中选择尽量少的喷水装置,把整个草坪全部润湿。

输入对于每一组输入,输出最多能够安排的活动数量。

每组的输出占一行样例输入221 1010 1131 1010 1111 20样例输出12提示注意:如果上一个活动在T时间结束,下一个活动最早应该在T+1时间开始。

解题思路:这是一个贪心法中选择不相交区间的问题。

先对活动结束时间从小到大排序,排序的同时活动的起始时间也要跟着变化。

而且,结束时间最小的活动一定会安排,不然这段时间就白白浪费了。

后一个活动的起始时间如果比前一个活动的结束时间大,即两个活动没有相交时间,就把这个活动也安排上。

c++贪心算法经典例题

c++贪心算法经典例题

c++贪心算法经典例题
经典的贪心算法例题有很多,以下是其中几个常见的例题:
1. 分糖果问题:
有一群小朋友,每个人都有一个评分。

现在需要给他们分糖果,要求评分高的小朋友比他旁边评分低的小朋友拥有更多的糖果。

求至少需要准备多少糖果。

2. 区间覆盖问题:
给定一个区间集合,每个区间表示一个工作时间段。

现在需要选择尽可能少的区间,覆盖整个时间范围。

求最少需要选择多少个区间。

3. 最佳买卖股票时机:
给定一个股票的价格列表,可以任意次数买入和卖出股票。

但是同一时间只能持有一支股票,求能够获得的最大利润。

4. 最大会议安排:
给定一系列的会议,每个会议有开始时间和结束时间。

要求安排尽可能多的会议,使得它们不会发生时间上的冲突。

5. 跳跃游戏:
给定一个非负整数数组,每个元素表示在该位置上能够跳跃的最大长度。

初始位置在第一个元素,判断能否跳到最后一个元素。

以上仅是一些常见的例题,贪心算法广泛应用于各种问题中。

在解决实际问题时,需要根据具体情况设计贪心策略,找到合适的贪心策略才能得到正确的解答。

贪心算法几个经典例子c语言

贪心算法几个经典例子c语言

贪心算法几个经典例子c语言1. 零钱兑换问题题目描述:给定一些面额不同的硬币和一个总金额,编写一个函数来计算可以凑成总金额所需的最少的硬币个数。

如果没有任何一种硬币组合能够凑出总金额,返回 -1。

贪心策略:每次选择面额最大的硬币,直到凑出总金额或者无法再选择硬币为止。

C语言代码:int coinChange(int* coins, int coinsSize, int amount){int count = 0;for(int i = coinsSize - 1; i >= 0; i--){while(amount >= coins[i]){amount -= coins[i];count++;}}return amount == 0 ? count : -1;}2. 活动选择问题题目描述:有 n 个活动,每个活动都有一个开始时间和结束时间,选择一些活动使得它们不冲突,且能够参加的活动数最多。

贪心策略:每次选择结束时间最早的活动,直到所有活动都被选择或者无法再选择为止。

C语言代码:typedef struct{int start;int end;}Activity;int cmp(const void* a, const void* b){return ((Activity*)a)->end - ((Activity*)b)->end;}int maxActivities(Activity* activities, int n){qsort(activities, n, sizeof(Activity), cmp);int count = 1;int end = activities[0].end;for(int i = 1; i < n; i++){if(activities[i].start >= end){count++;end = activities[i].end;}}return count;}3. 跳跃游戏题目描述:给定一个非负整数数组,你最初位于数组的第一个位置。

第4章 贪心算法(1)活动安排问题

第4章 贪心算法(1)活动安排问题
3
4.1 活动安排问题
活动安排问题是可以用贪心算法有效求解的很 好例子。
该问题要求高效地安排一系列争用某一公共资 源的活动,使得尽可能多的活动能兼容地使用 公共资源。
4
问题描述
设有n个活动的集合E={1, 2, …, n},其中每个 活动都要求使用同一资源,而在同一时间内只 有一个活动能使用这一资源。
2
贪心算法
例2:若上述硬币面值改为:
一角一分、五分和一分 现在要找给顾客一角五分钱,如何给出硬币? 答案:错:1个一角一分,4个一分
对:3个五分
虽然贪心算法不能对所有问题都得到整体最优 解,但对许多问题它能产生整体最优解。
在一些情况下,即使贪心算法不能得到整体最 优解,其最终结果却是最优解的很好的近似解。
ቤተ መጻሕፍቲ ባይዱ17
0-1背包问题
给定n种物品和一个背包。物品i的重量是wi, 其价值为vi,背包的容量为c。应如何选择装 入背包的物品,使得装入背包中物品的总价 值最大?
说明:在选择装入背包的物品时,对每种物 品i只有2种选择,即装入背包或不装入背包。 不能将物品i装入背包多次,也不能只装入部 分的物品i。
16
3、贪心算法与动态规划算法的 差异
贪心算法和动态规划算法都要求问题具有最 优子结构性质,这是两类算法的一个共同点。
对于具有最优子结构的问题应该选用贪心算 法还是动态规划算法求解?
是否能用动态规划算法求解的问题也能用贪 心算法求解?
下面研究2个经典的组合优化问题,并以此 说明贪心算法与动态规划算法的主要差别。
每个活动i都有一个要求使用该资源的起始时 间si和一个结束时间fi,且si <fi 。
5
问题描述
如果选择了活动i,则它在半开时间区间[si, fi) 内占用资源。若区间[si, fi)与区间[sj, fj)不相交, 则称活动i与活动j是相容的。也就是说,当si≥fj

因为贪心而失败的例子

因为贪心而失败的例子

因为贪心而失败的例子贪心算法是一种常用的解决问题的算法思想,它通常在每一步选择中都采取当前状态下最好或最优的选择,从而希望最终能够达到全局最优的结果。

然而,贪心算法的贪心选择可能会导致最终结果并非全局最优,而是局部最优或者根本无法得到可行解。

因此,贪心算法在某些问题上会因为贪心而失败。

下面将列举10个因为贪心而失败的例子。

1. 颜色分配问题:假设有n个节点需要着色,并且相邻的节点不能具有相同的颜色。

贪心算法选择每次都选择可用颜色最少的节点进行着色。

然而,这种贪心选择可能会导致最终无法着色所有节点,因为后续节点的颜色选择受到前面节点的限制。

2. 找零问题:假设需要找零的金额为m,而只有面额为1元、5元、10元的硬币。

贪心算法选择每次都选择面额最大的硬币进行找零。

然而,在某些情况下,贪心选择可能会导致找零的硬币数量不是最小的。

3. 最小生成树问题:在一个连通图中,选择一些边构成一个树,使得这些边的权值之和最小,同时保证图中的所有节点都能够通过这些边连通。

贪心算法选择每次都选择权值最小的边加入到树中。

然而,这种贪心选择可能会导致最终得到的树不是最小生成树。

4. 背包问题:给定一组物品,每个物品有自己的重量和价值,在给定的背包容量下,选择一些物品放入背包中,使得背包中物品的总价值最大。

贪心算法选择每次都选择单位重量价值最大的物品放入背包中。

然而,在某些情况下,贪心选择可能会导致最终得到的背包价值不是最大的。

5. 最短路径问题:在一个有向图中,找到两个节点之间的最短路径。

贪心算法选择每次都选择距离最近的节点进行扩展。

然而,这种贪心选择可能会导致最终得到的路径不是最短的。

6. 任务调度问题:给定一组任务,每个任务有自己的开始时间和结束时间,在给定的时间段内,选择一些任务进行调度,使得能够完成尽可能多的任务。

贪心算法选择每次都选择结束时间最早的任务进行调度。

然而,在某些情况下,贪心选择可能会导致最终完成的任务数量不是最多的。

信息学竞赛中的模拟与贪心算法模板

信息学竞赛中的模拟与贪心算法模板

信息学竞赛中的模拟与贪心算法模板在信息学竞赛中,模拟与贪心算法是常用的解题思路之一。

它们能够在面对各种问题时提供简洁高效的解决方案。

本文将介绍信息学竞赛中常用的模拟与贪心算法模板,帮助选手更好地应对竞赛题目。

一、模拟算法模板模拟算法通过模拟问题的过程,逐步逼近问题的答案。

常见的模拟算法包括枚举、模拟、暴力搜索等。

下面将以几个经典的问题为例,介绍模拟算法的模板。

1. 枚举枚举是一种穷举所有可能的方法。

可以用来解决一些指定范围内的问题,如排列组合、数字结构等。

常见的枚举方法有递归枚举、位运算枚举等。

2. 模拟模拟是一种按照题目要求,逐步模拟问题的过程。

通常需要设计好数据结构和算法,以便进行模拟计算。

在模拟算法中,需注意边界条件的处理,以确保模拟的正确性。

3. 暴力搜索暴力搜索是一种穷举所有可能情况的方法,通过遍历搜索空间,找到问题的所有可能解。

暴力搜索常用于解决规模较小的问题,时间复杂度较高。

二、贪心算法模板贪心算法是一种在每一步都选择当前状态下最优解的算法。

它通过局部最优解的选择,逐步构建出全局最优解。

贪心算法的关键在于确定每一步的最优选择策略。

常见的贪心算法模板如下:1. 确定问题的贪心策略贪心算法的关键在于确定每一步的最优选择。

根据问题的性质,分析问题的特点,选择适当的贪心策略。

2. 构建贪心算法的循环根据确定的贪心策略,使用循环来逐步构建解决方案。

在每一步选择最优解后,更新相关状态,并进入下一步。

3. 判断是否达到全局最优解判断当前选择是否达到全局最优解。

如果是,则终止算法并输出结果;否则继续选择下一步的最优解。

贪心算法的设计思路需要充分理解问题本身,熟悉问题的特点,并根据实际情况灵活运用。

总结:信息学竞赛中,模拟与贪心算法是常用的解题思路。

本文介绍了模拟算法和贪心算法的模板。

在实际应用时,选手们需要根据题目要求和问题的特点,灵活运用这些模板,找到最适合的解决方案。

通过不断的练习和实践,提升自己的解题能力,在竞赛中取得优异的成绩。

贪心算法通过每次选择局部最优解来达到全局最优

贪心算法通过每次选择局部最优解来达到全局最优

贪心算法通过每次选择局部最优解来达到全局最优贪心算法是一种常用的解决优化问题的算法。

它通过每次选择局部最优解来达到全局最优的目标。

在本文中,我们将介绍贪心算法的原理、应用场景以及优缺点。

一、原理贪心算法的基本原理非常简单:每一步都选择当前状态下的局部最优解,最终得到的结果就是全局最优解。

贪心算法不考虑过去的选择对未来的影响,只关注眼前的最佳选择。

二、应用场景贪心算法在各个领域都有广泛的应用,下面我们将以几个常见的实际问题来说明。

1. 图的最小生成树问题在一个连通无向图中,找到一个包含所有节点且权值最小的无回路子图,这个问题称为最小生成树问题。

贪心算法可以通过每次选择权值最小的边来逐步构建最小生成树。

2. 分糖果问题有一组孩子和一组糖果,每个孩子有一个需求因子和每个糖果有一个大小。

当糖果的大小不小于孩子的需求因子时,孩子可以获得该糖果。

目标是尽可能多地满足孩子的需求,贪心算法可以通过给每个孩子分配满足其需求因子的最小糖果来达到最优解。

3. 区间调度问题给定一个任务列表,每个任务有一个开始时间和结束时间。

目标是安排任务的执行顺序,使得尽可能多的任务能够被完成。

贪心算法可以通过选择结束时间最早的任务来实现最优解。

以上只是一些贪心算法的应用场景,实际上贪心算法可以用于解决各种优化问题。

三、优缺点1. 优点①简单:贪心算法的思路相对简单,容易理解和实现。

②高效:由于只考虑局部最优解,贪心算法的时间复杂度较低,通常能够在较短的时间内得到一个接近最优解的结果。

③可用于近似求解:由于贪心算法不保证得到全局最优解,但可以用于求解近似最优解的问题。

2. 缺点①不保证全局最优解:贪心算法只考虑眼前的最优选择,无法回溯和修正过去的选择,因此不能保证得到全局最优解。

②局部最优解无法转移:在某些情况下,局部最优解并不一定能够转移到全局最优解,导致贪心算法得到的结果偏离最优解。

③对问题的要求较高:由于贪心算法需要找到适合的局部最优解,因此问题必须具备一定的特殊性,而一些问题无法使用贪心算法解决。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

4.5 哈夫曼编码
哈夫曼编码是一种被广泛应用而且非常有效的数据压缩技术,哈夫曼根据字符在文件中出现的不同频率来建立一个用0,1串表示各字符的最优编码树(称为哈夫曼树),它的设计也是贪心选择的一个典型例子。

例假设有一个包含10000个只含a,b,c,d,e,f字符的数据文件,各字符在文件中出现的频率见下4.5.1表
表 4.5.1
若采用等长编码,则需3位二进制数位来表示6个字符,这种方法要用30000位来表示整个文件。

若采用变长编码,则整个文件只需
(45×1+13×3+12×3+16×3+9×4+5×4) ×100=22400 位
也就是说压缩了 (30000-22400)÷30000×100%≥25% 。

实际上,这就是这个文件的最优编码方案了
4.5.1 前缀码
我们对每一字符规定一个0,1串作为其代码,并要求任一字符代码都不是其他字符代码的前缀,这样的编码简称为前缀码。

在4.5.1表中的两种编码都是前缀码。

由于任一字符代码都不是其他字符代码的前缀,所以译码方法非常简单。

为了在译码过程中方便地取出编码的前缀,我们可以用二叉树作为前缀码的数据结构。

在表示前缀码的二叉树中,树叶代表给定的字符,并将每个字符的前缀码看作是从树根到代表该字符的树叶的一条道路。

代码中每一位的0或1分别作为指示某结点到左儿子或右儿子的路标。

如图4-1中的两棵二叉树是表4.5.1中两种编码方案所对应的数据结构。

图 4-1 前缀码的二叉树表示
容易看出,表示最优编码方案所对应的前缀码的二叉树总是一棵完全二叉树,即树中任一结点都有2个儿子。

而定长编码方案不是最优的,其编码的二叉树不是一棵完全二叉树。

在一般情况下,若C是编码字符集,包含有n个字符,则表示其最优前缀码的二叉树中恰好有n个叶子。

每个叶子对应于字符集中一个字符,且该二叉树恰好有n - 1个内部结点。

4.6 最小生成树
设G= (V ,E )是一个无向连通图,即一个网络。

给 E 的每一条边(v, w )赋于一个权。

如果G 的一个子图G ˊ是一棵包含G 的所有顶点的树,则称G ˊ为G 的生成树。

生成树上各边权的总和称为该生成树的代价。

在G 的所有生成树中,代价最小的生成树称为G 的最小生成树。

网络的最小生成树在实际中有着广泛的应用。

在不同的背景下,边的权可以代表不同的含义,比如,两点间的距离,两点间的公路造价等等。

例如,在设计通信网络时,用图的顶点表示城市,用边(v, w )的权表示建立城市v 和城市w 的之间的通信线路所需的费用,则最小生成树就给出了建立通信网络的最经济的方案。

用贪心算法设计策略可以设计出构造最小生成树的有效算法。

本节中要介绍的构造最小生成树的Prim 算法和Kruskal 算法都可以看作是应用贪心算法设计策略的典型例子。

4.6.1 Prim 算法
设G= (V ,E )是一个连通带权图,V={1 ,2 ,···,n} ,二维数组W 的元素W[i][j] 表示边(i ,j )的权。

构造G 的一棵最小生成树的Prim 算法的基本思想是:首先置S={1} ,
然后,只要S 是V 的真子集,就作如下的贪心选择:选取满足条件i ∈S ,j ∈V -S ,且W[i][j] 最小的边,并将顶点j 添加到S 中。

这个过程一直进行到S=V 时为止。

在这个过程中选取到的所有边恰好构成G 的一棵最小生成树T 。

Prim 算法:
S1. T= Æ ,S={1} ,mincost=0
S2. 当S<>V 时转S3 ,否则转S7
S3. 设(i ,j )是所有k ∈S ,l ∈V - S 的边(k ,l )中权最小的边
S4. T=T ∪{ (i ,j )}
S5. S=S ∪{ j }
S6. mincost=mincost+W[i][j] ,转S2
S7. 输出T ,mincost
其实,S 并不一定从顶点1 开始,可以从任一个顶点开始。

例对于图4 -3 a ,图4 -3 b 是Prim 算法生成最小生成树的过程。

图4 -3 a 图 4 -3 b 最小生成树的生成过程
算法实现时,时间主要消耗在双层循环上,所以总的时间复杂性为○ (n2)。

4.7 单源最短路径问题
给定一个带权有向图G=(V,E),其中每条边的权是一个非负数。

另外,还给定V中的一个顶点,称为源。

现在我们要计算从源到所有其他各个顶点的最短路长度。

这里路的长度是指路上各边权之和。

这个问题称为单源最短路径问题。

Dijkstra算法是解单源最短路径问题的一个贪心算法。

其基本思想是:设置一个顶点集合S并不断地作贪心选择来扩充这个集合。

一个顶点属于集合S
当且仅当从源到该顶点的最短路径长度已知。

初始时,S中仅含有源。

设u是G 的某一个顶点,我们把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组DIST来记录当前每个顶点所对应的最短特殊路径长度。

Dijkstra 算法每次从V-S中取出具有最短特殊路径长度的顶点u添加到S中。

当顶点u
添加到S中后,与顶点u相临的顶点v的最短特殊路径长度可能改变,如果长度改变了,则它必定是由一条从源开始,经过u然后到w的更短的路所造成的,此时,可以修改DIST[w]=DIST[u]+边(u, w)的权。

一旦S包含了V中的所有顶点,DIST就记录了从源到所有其他顶点之间的最短路径长度。

在下面的算法中,集合S用一个数组来表示,顶点i属于S,则S[i]=1,否则S[i]=0;W是一个二维数组,W[i][j]表示边(i, j)的权。

当(i, j)?E时,W[i][j]可设置为一个大数(比如+∞);顶点v是源。

Dijkstra算法:
S1. i=1
S2. 若i≤n 转S3,否则转S4
S3. S[i]=0,DIST[i]=W[v, i],i=i+1 转S2
S4. S[v]=1,DIST[v]=0
S5. i=1
S6. 若i≤n-1 转S7,否则转S11
S7. 选取u,它使
S8. S[u]=1
S9. 对所有S[w]=0的结点作:
若DIST[w] > DIST[u]+W[u][w],则DIST[w]=DIST[u]+W[u][w]
S10. i=i+1,转S6
S11. 输出DIST
上述算法只求出从源到所有其他各个顶点间的最短路径长度。

如果还要求出相应的最短路径,需修改算法。

请读者自己完成。

对于一个具有n个顶点和e条边的带权有向图,Dijkstra算法的主循环体需要○(n)时间。

这个循环需要执行n-1 次,所以完成循环需要○( n2 ) 。

算法的其他部分所需要的时间不超过○( n2 ),所以Dijkstra算法的时间复杂性为○( n2 )。

例对图4-6中的有向图,表4.7.1列出了应用Dijkstra算法计算从源顶点1到其他顶点间最短路径长度的过程
迭代 S u DIST[2] DIST[3] DIST[4] DIST[5]
初始 {1} - 10 +∞ 30 100
1 {1,2}
2 10 60 30 100
2 {1,2,4} 4 10 50 30 90
3 {1,2,4,3} 3 10 50 30 60
4 {1,2,4,3,5}
5 10 50 30 60
表4.7.1 Dijkstra算法的迭代过程
本小节习题:
(1) 修改Dijkstra算法,使得在求最短路径长度的同时得到这些最短路径。

(2) 用修改后的Dijkstra算法求有向带权图4-7中由顶点1到其他顶点的最短路径长度和最短路径。

.
图4-7 有向带权图。

相关文档
最新文档