贪心法解活动安排问题(计算机算法设计与分析)
贪心算法(4):活动选择问题

贪⼼算法(4):活动选择问题我们继续回到上⼀堂课留下的课外习题:活动选择问题。
活动选择问题是很常见的场景。
例如各个部门共享⼀个会议室,利⽤该算法能使会议室安排尽量多的会议。
【问题】给你n个活动的开始时间和结束时间,从中选择你可以参与的活动,但是同⼀时间你只能参与⼀个活动,请找出你可以参与的最多活动数。
例如:考虑下⾯3个活动a1,a2和a3, 它们{开始时间点,结束时间点}分别为:a1 {start=10,finish=20}a2 {start=12,finish=25}a3 {start=20,finish=30}贪⼼算法直接在每⼀步选择当前看来最好的选择。
在开始时,选择活动结束时间最早的那个活动,这样能够给其他活动尽可能的腾出多余的时间。
⽽后每⼀步都在剩下的活动中选取,也遵循类似的原则。
由于获取已经按照结束时间排序好,所以这⾥第⼀个选择的活动就是a0,由于a0于时间20结束,马上再找⼀个活动,只有a2可以选择,a2结束之后再也没有活动可选了。
因此得到答案:最多可以参加两个活动(a0,a2)。
算法分析和设计现在请你设计⼀种贪⼼算法解决类似活动选择问题。
我们设计下列贪⼼算法的贪⼼策略:选择其余活动中完成时间最短的下⼀个活动,并且开始时间⼤于或等于先前所选活动的结束时间。
我们可以根据他们的完成时间对活动进⾏排序,以便我们始终将下⼀个活动视为最⼩完成时间活动。
算法描述如下{k}}U{1},必定仍然是⼀个最佳解决⽅案,说明如下:因为S 中的活动是独⽴的,⽽在排序队列中,【活动1】在所有活动中具有最⼩的结束时间,因为k不等于1,【活动k】的完成时间必定是⼤于等与【活动1】的完成时间,因此把【活动k】换成【活动1】后的新⽅案S‘必定也是最佳解决⽅案。
算法实现在以下C/C++代码实现中,假设活动已根据其完成时间进⾏了排序。
#include<stdio.h>// n --> 活动个数// s[] --> 数组保存所有活动的开始时间// f[] --> 数组保存所有活动的结束时间void printMaxActivities(int s[], int f[], int n){int i, j;printf ('选择以下的活动\n');// 第⼀个活动总是选中i = 0;printf('%d ', i);// 依次检查余下的活动for (j = 1; j < n; j++){//如果某活动在之前选择的活动结束之后开始if (s[j] >= f[i]){printf ('%d ', j);i = j;}}}//主程序int main(){int s[] = {1, 3, 0, 5, 8, 5};int f[] = {2, 4, 6, 7, 9, 9};int n = sizeof(s)/sizeof(s[0]);printMaxActivities(s, f, n);return 0;}注意:若是finish数组没有排序,需要先对它进⾏排序。
c++贪心算法经典例题

c++贪心算法经典例题
经典的贪心算法例题有很多,以下是其中几个常见的例题:
1. 分糖果问题:
有一群小朋友,每个人都有一个评分。
现在需要给他们分糖果,要求评分高的小朋友比他旁边评分低的小朋友拥有更多的糖果。
求至少需要准备多少糖果。
2. 区间覆盖问题:
给定一个区间集合,每个区间表示一个工作时间段。
现在需要选择尽可能少的区间,覆盖整个时间范围。
求最少需要选择多少个区间。
3. 最佳买卖股票时机:
给定一个股票的价格列表,可以任意次数买入和卖出股票。
但是同一时间只能持有一支股票,求能够获得的最大利润。
4. 最大会议安排:
给定一系列的会议,每个会议有开始时间和结束时间。
要求安排尽可能多的会议,使得它们不会发生时间上的冲突。
5. 跳跃游戏:
给定一个非负整数数组,每个元素表示在该位置上能够跳跃的最大长度。
初始位置在第一个元素,判断能否跳到最后一个元素。
以上仅是一些常见的例题,贪心算法广泛应用于各种问题中。
在解决实际问题时,需要根据具体情况设计贪心策略,找到合适的贪心策略才能得到正确的解答。
贪心算法程序设计

贪心算法程序设计贪心算法程序设计1. 什么是贪心算法贪心算法(Greedy Algorithm)是一种常见的算法思想,它在每一步选择中都采取当前状态下的最优选择,从而希望最终达到全局最优解。
贪心算法的核心思想是局部最优解能导致全局最优解。
2. 贪心算法的基本步骤贪心算法的基本步骤如下:1. 定义问题的优化目标。
2. 将问题分解成子问题。
3. 选择当前最优的子问题解,将子问题的解合并成原问题的解。
4. 检查是否达到了问题的优化目标,如果没有达到,则回到第二步,继续寻找下一个最优子问题解。
5. 在所有子问题解合并成原问题解后,得到问题的最优解。
3. 贪心算法的应用场景贪心算法的应用非常广泛,几乎可以用于解决各种优化问题。
以下几个常见的应用场景:1. 零钱找零问题:给定一定面额的纸币和硬币,如何找零使得所需纸币和硬币的数量最小?2. 区间调度问题:给定一些活动的开始时间和结束时间,如何安排活动使得可以办理的活动数量最大?3. 背包问题:给定一些具有重量和价值的物品,如何选择物品使得背包的总价值最大?4. 最小树问题:给定一个带权无向图,如何找到一棵树,使得它的边权之和最小?5. 哈夫曼编码问题:给定一组字符和相应的频率,如何构造一个满足最低编码长度限制的二进制编码?4. 贪心算法的优缺点贪心算法的优点是简单、高效,可以快速得到一个近似最优解。
而且对于一些问题,贪心算法能够得到全局最优解。
贪心算法的缺点在于它不一定能够得到全局最优解,因为在每一步只考虑局部最优解,无法回溯到之前的选择。
5. 贪心算法的程序设计在使用贪心算法进行程序设计时,通常需要以下几个步骤:1. 定义问题的优化目标。
2. 将问题分解成子问题,并设计子问题的解决方案。
3. 设计贪心选择策略,选择局部最优解。
4. 设计贪心算法的递推或迭代公式。
5. 判断贪心算法是否能够得到全局最优解。
6. 编写程序实现贪心算法。
6.贪心算法是一种常见的算法思想,它在每一步选择中都采取当前状态下的最优选择,从而希望最终达到全局最优解。
4-贪心法

应用实例
活动安排问题—算法设计与分析
template<class Type> void GreedySelector(int n, Type s[], Type f[], bool A[]) { A[1] = true; int j = 1; for (int i=2;i<=n;i++) { if (s[i]>=f[j]) { A[i]=true; j=i; } else A[i]=false; } }
贪心法的正确性问题
针对具体问题不同,贪心策略的选择可能有多种 ,如何选择合适的贪心策略并证明该策略的正确 性是贪心算法设计中的一个关键问题。 一般可以通过对算法步数的归纳或通过对问题规 模的归纳来证明贪心法的正确性。
应用实例
活动安排问题
有n个活动申请使用同一个礼堂,每项活动有一个开始时间和一 个截止时间,如果任何两个活动不能同时举行,问如何选择这 些活动,从而使得被安排的活动数量达到最多? 设S={1, 2, …, n}为活动的集合,si和fi分别为活动i的开始和截止 时间,i=1, 2, …, n。定义 活动i与j相容:si ≥ fj或sj ≥fi, i≠j 求S最大的两两相容的活动子集。 蛮力法 动态规划方法
若硬币的面值改为一角一分、五分和一分,要找给顾客的 是一角五分,情况如何?
贪心算法的基本思想
顾名思义,贪心算法总是作出在当前看来最好的 选择。也就是说贪心算法并不从整体最优考虑, 它所作出的选择只是在某种意义上的局部最优选 择。 贪心算法不能对所有问题都得到整体最优解,但 对许多问题它能产生整体最优解。 在一些情况下,即使贪心算法不能得到整体最优 解,其最终结果却是最优解的很好近似。
4—贪心法 Greedy Approach
算法设计与分析第04章 贪心算法PPT课件

4.1 活动安排问题
若被检查的活动i的开始时间Si小于最近选择的活动j 的结束时间fi,则不选择活动i,否则选择活动i加入集 合A中。
贪心算法并不总能求得问题的整体最优解。但对 于活动安排问题,贪心算法greedySelector却总能求 得的整体最优解,即它最终所确定的相容活动集合A的 规模最大。这个结论可以用数学归纳法证明。
•}
6
4.1 活动安排问题
由于输入的活动以其完成时间的非减序排列,所 以算法greedySelector每次总是选择具有最早完成 时间的相容活动加入集合A中。直观上,按这种方法 选择相容活动为未安排活动留下尽可能多的时间。也 就是说,该算法的贪心选择的意义是使剩余的可安排 时间段极大化,以便安排尽可能多的相容活动。
算法greedySelector的效率极高。当输入的活 动已按结束时间的非减序排列,算法只需O(n)的时间 安排n个活动,使最多的活动能相容地使用公共资源。 如果所给出的活动未按非减序排列,可以用O(nlogn) 的时间重排。
7
4.1 活动安排问题
例:设待安排的11个活动的开始时间和结束时间按结 束时间的非减序排列如下:
13
4.2 贪心算法的基本要素
3.贪心算法与动态规划算法的差异
贪心算法和动态规划算法都要求问题具有最优子结构 性质,这是2类算法的一个共同点。但是,对于具有最 优子结构的问题应该选用贪心算法还是动态规划算法 求解?是否能用动态规划算法求解的问题也能用贪心算 法求解?下面研究2个经典的组合优化问题,并以此说 明贪心算法与动态规划算法的主要差别。
11
4.2 贪心算法的基本要素
1.贪心选择性质
所谓贪心选择性质是指所求问题的整体最优解可以通 过一系列局部最优的选择,即贪心选择来达到。这是 贪心算法可行的第一个基本要素,也是贪心算法与动 态规划算法的主要区别。
算法分析与设计实验三贪心算法

实验三贪心算法实验目的1. 掌握贪心法的基本思想方法;2. 了解适用于用贪心法求解的问题类型,并能设计相应贪心法算法;3. 掌握贪心算法复杂性分析方法分析问题复杂性。
预习与实验要求1. 预习实验指导书及教材的有关内容,掌握贪心法的基本思想;2. 严格按照实验内容进行实验,培养良好的算法设计和编程的习惯;3. 认真听讲,服从安排,独立思考并完成实验。
实验设备与器材硬件:PC机软件:C++或Java等编程环境实验原理有一类问题是要从所有的允许解中求出最优解,其策略之一是“贪心法”,即逐次实施“贪心选择”:在每个选择步骤上做出的选择都是当前状态下最优的。
贪心选择依赖于在此之前所做出的选择,但不依赖于后续步骤所需要的选择,即不依赖于后续待求解子问题。
显然,这种选择方法是局部最优的,但不是从问题求解的整体考虑进行选择,因此不能保证最后所得一定是最优解。
贪心法是求解问题的一种有效方法,所得到的结果如果不是最优的,通常也是近似最优的。
实验内容以下几个问题选做一项:1. 用贪心法实现带有期限作业排序的快速算法应用贪心设计策略来解决操作系统中单机、无资源约束且每个作业可在等量时间内完成的作业调度问题。
假定只能在一台机器上处理N个作业,每个作业均可在单位时间内完成;又假定每个作业i都有一个截止期限di>0(它是整数),当且仅当作业i在它的期限截止以前被完成时,则获得pi的效益。
这个问题的一个可行解是这N个作业的一个子集合J,J中的每个作业都能在各自的截止期限之前完成。
可行解的效益值是J中这些作业的效益之和,即Σp。
具有最大效益值的可行解就是最优解。
2. 实现K元归并树贪心算法两个分别包含n个和m个记录的已分类文件可以在O(n+m)时间内归并在一起而得到一个分类文件。
当要把两个以上的已分类文件归并在一起时,可以通过成对地重复归并已分类的文件来完成。
例如:假定X1,X2,X3,X4是要归并的文件,则可以首先把X1和X2归并成文件Y1,然后将Y1和X3归并成Y2,最后将Y2和X4归并,从而得到想要的分类文件;也可以先把X1和X2归并成Y1,然后将X3和X4归并成Y2,最后归并Y1和Y2而得到想要的分类文件。
c++贪心算法经典例题

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` 用于排序。
贪心算法PPT课件

安排方案
f1
B
安排方案
fk
B’
…… 共j个活动
可能 相同 不存在
……
可能
如果 B’包 含这 个活, 则B 一定 包含
9
(2) 时间复杂度分析: 因为排序过程可以在O(nlogn)时间内完成,而求最优活动子 集的过程只需O(n)次比较,因此这个算法的时间复杂度为 O(nlogn)。 (3) 贪心策略设计算法的一般特点
·选Si最小的,这样可以增大场地的利用率; ·选fi最小的,使得下一个活动可以更早开始。
由于活动的占用时间长度没有限制,因此后一选择更合理。
6
为了在每一次选择时取当前可以安排的活动中最早结束的活动,应首先把 n项活动按结束时间的先后进行升序排序。即,使f1≤f2≤…≤fn,然后在Si值 不小于当前时刻的活动中取fi值最小者。 算法:
·算法的设计比较简单; ·算法一般比较快速; ·算法的正确性一般不明显,需要论证;如果正确性不能保 证,那么它往往可以得到近似最优解。
10
5.2 背包(Knapsack)问题
1. 问题描述
已知:n个(应为n种)物体{1,2,…,n}与一个背包。物体i的重量 (或体积)为Wi>0,价值为Pi>0(i=1,2,…,n),背包容量为 M>0。
计算机算法 ——设计与分析导论
刘璟
1
Chapter 5. 贪心(Greedy)技术
❖ 5.1 贪心策略的思想 ❖ 5.2 背包(Knapsack)问题 ❖ 5.3 Huffman编码 ❖ 5.4 多机调度问题的近似解法 ❖ 5.5 单源最短路径的Dijkstra算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验报告
课程名称:算法设计与分析实验名称:贪心法解活动安排问题任课教师:专业:计算机科学与技术
班级: 20xx 级x班学号:
姓名:完成日期: 20xx年x月xx日
五、实验总结
在做本实验之前,自己看了课本上所列举的贪心法解活动安排问题的代码,代码很简单,很容易理解,于是就按课本的代码实现。
通过几个测试用例测试发现结果不对,后来发现自己忘了进行贪心法的一个前提条件,事先没有按各个活动结束时间对所有活动进行非递减排序,所以才会导致结果错误。
经过修正后,自己真正理解了贪心法解活动安排问题的原理,重新完成本次实验内容也是很顺利,在编程方面没有遇到什么困难。