贪心法解活动安排问题(计算机算法设计与分析)
- 格式:doc
- 大小:122.50 KB
- 文档页数:6
贪⼼算法(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++贪心算法经典例题
经典的贪心算法例题有很多,以下是其中几个常见的例题:
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.贪心算法是一种常见的算法思想,它在每一步选择中都采取当前状态下的最优选择,从而希望最终达到全局最优解。
实验三贪心算法实验目的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++贪心算法经典例题和详解贪心算法(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` 用于排序。
贪心算法解决活动安排问题金潇Use the greedy algorithm to solve the arrangement for activitiesJinxiao摘要:贪心算法在当前来看是最好的选择。
是用利用启发式策略,在不从整体最优上加以考虑的情况下,来做出局部最优选择的一种算法。
本文通过贪心算法的经典案例—活动安排问题入手,描述了贪心算法的基本思想和可能产生的问题,并简述该算法的好处和特点,最后给出几种经典的贪心算法。
关键字:贪心算法、局部最优选择Abstract:A greedy algorithm is any algorithm that follows the problem solving heuristic of making the locally optimal choice at each stage with the hope of finding the global optimum. This article through the greedy algorithm of the classic case--activities problems, describes the greedy algorithm the basic ideas and possible problems, and briefly introduces the advantages and characteristics of the algorithm, and finally gives several classic the greedy algorithm. Keywords:greedy algorithm、the locally optimal choice1.引言:贪心法是一种改进了的分级处理方法。
用贪心法设计算法的特点是一步一步地进行,每一步上都要保证能获得局部最优解。
列举用贪心算法求解的经典问题
1. 零钱兑换问题:给定一些面值不同的硬币和一个金额,要求用最少的硬币凑出这个金额。
2. 最小生成树问题:给定一个无向带权图,要求用最小的权值构建一棵生成树。
3. 背包问题:给定一些物品和一个背包,每个物品有对应的价值和重量,要求在背包容量限制下,选取物品使得总价值最大。
4. 活动安排问题:有若干个活动需要分配一段时间,每个活动有对应的开始时间和结束时间,要求选取尽可能多的活动,使得任两个安排的活动时间不重叠。
5. 单源最短路径问题:给定一个有向带权图和一个起始节点,要求求出从起始节点到其他所有节点的最短路径。
6. 任务调度问题:有若干个需要完成的任务和多个可执行任务的处理器,要求将任务分配给处理器,使得执行总时间最小。
7. 区间覆盖问题:给定一些区间,要求用尽可能少的区间覆盖整个线段。
8. 哈夫曼编码问题:给定一些字符及其对应的出现概率,要求用最短的编码方式表示这些字符。
[C++]贪⼼算法之活动安排、背包问题⼀、贪⼼算法的基本思想 在求解过程中,依据某种贪⼼标准,从问题的初始状态出发,直接去求每⼀步的最优解,通过若⼲次的贪⼼选择,最终得出整个问题的最优解。
从贪⼼算法的定义可以看出,贪⼼算法不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,⽽由问题⾃⾝的特性决定了该题运⽤贪⼼算法可以得到最优解。
如果⼀个问题可以同时⽤⼏种⽅法解决,贪⼼算法应该是最好的选择之⼀。
⼆、贪⼼算法的基本要素 (1)最优⼦结构性质 (2)贪⼼选择性质(局部最优选择)三、贪⼼算法实例 1、活动安排 设有n个活动的集合 E = {1,2,…,n},其中每个活动都要求使⽤同⼀资源,如演讲会场等,⽽在同⼀时间内只有⼀个活动能使⽤这⼀资源。
每个活动 i 都有⼀个要求使⽤该资源的起始时间 s i和⼀个结束时间 f i,且 s i< f i。
如果选择了活动i,则它在半开时间区间 [s i ,f i ) 内占⽤资源。
若区间 [s i , f i )与区间 [s j, f j ) 不相交,则称活动i与活动j是相容的。
当 s i ≥ f j或 s j ≥ f i时,活动 i 与活动 j 相容。
活动安排问题就是在所给的活动集合中选出最⼤的相容活动⼦集合。
例如:1 #include <iostream>2 using namespace std;34 #define NUM 5056 void GreedySelector(int n, int s[], int f[], bool b[])7 {8 b[1]=true; //默认将第⼀个活动先安排9 int j=1; //记录最近⼀次加⼊b中的活动1011 //依次检查活动i是否与当前已选择的活动相容12 for(int i=2;i<=n;i++)13 {14 if (s[i]>=f[j])15 {16 b[i]=true;17 j=i;18 }19 else20 b[i]=false;21 }22 }2324 int main()25 {26 int s[] = {0,1,3,0,5,3,5,6,8,8,2,12}; //存储活动开始时间27 int f[] = {0,4,5,6,7,8,9,10,11,12,13,14}; //存储活动结束时间28 bool b[NUM]; //存储被安排的活动编号29 int n = (sizeof(s) / sizeof(s[0])) - 1;3031 GreedySelector(n, s, f, b);3233 for(int i = 1; i <= n; i++) //输出被安排的活动编号和它的开始时间和结束时间34 {35 if(b[i]) cout << "活动 " << i << " :" << "(" << s[i] << "," << f[i] << ")" <<endl;36 }37 return 0;38 } 2、背包问题 给定⼀个载重量为 M 的背包,考虑 n 个物品,其中第 i 个物品的重量 w i(1 ≤ i ≤ n),价值 v i(1 ≤ i ≤ n),要求把物品装满背包,且使背包内的物品价值最⼤。
《计算机算法设计与分析》习题及答案一.选择题1、二分搜索算法是利用( A )实现的算法。
A、分治策略B、动态规划法C、贪心法D、回溯法2、下列不是动态规划算法基本步骤的是( A )。
A、找出最优解的性质B、构造最优解C、算出最优解D、定义最优解3、最大效益优先是( A )的一搜索方式。
A、分支界限法B、动态规划法C、贪心法D、回溯法4. 回溯法解旅行售货员问题时的解空间树是( A )。
A、子集树B、排列树C、深度优先生成树D、广度优先生成树5.下列算法中通常以自底向上的方式求解最优解的是( B )。
A、备忘录法B、动态规划法C、贪心法D、回溯法6、衡量一个算法好坏的标准是( C )。
A 运行速度快B 占用空间少C 时间复杂度低D 代码短7、以下不可以使用分治法求解的是( D )。
A 棋盘覆盖问题B 选择问题C 归并排序D 0/1背包问题8. 实现循环赛日程表利用的算法是( A )。
A、分治策略B、动态规划法C、贪心法D、回溯法9.下面不是分支界限法搜索方式的是( D )。
A、广度优先B、最小耗费优先C、最大效益优先D、深度优先10.下列算法中通常以深度优先方式系统搜索问题解的是( D )。
A、备忘录法B、动态规划法C、贪心法D、回溯法11.备忘录方法是那种算法的变形。
( B )A、分治法B、动态规划法C、贪心法D、回溯法12.哈夫曼编码的贪心算法所需的计算时间为( B )。
A、O(n2n)B、O(nlogn)C、O(2n)D、O(n)13.分支限界法解最大团问题时,活结点表的组织形式是( B )。
A、最小堆B、最大堆C、栈D、数组14.最长公共子序列算法利用的算法是( B )。
A、分支界限法B、动态规划法C、贪心法D、回溯法15.实现棋盘覆盖算法利用的算法是( A )。
A、分治法B、动态规划法C、贪心法D、回溯法16.下面是贪心算法的基本要素的是( C )。
A、重叠子问题B、构造最优解C、贪心选择性质D、定义最优解17.回溯法的效率不依赖于下列哪些因素( D )A.满足显约束的值的个数B. 计算约束函数的时间C.计算限界函数的时间D. 确定解空间的时间18.下面哪种函数是回溯法中为避免无效搜索采取的策略( B )A.递归函数 B.剪枝函数 C。
实验报告
课程名称:算法设计与分析实验名称:贪心法解活动安排问题任课教师:专业:计算机科学与技术
班级: 20xx 级x班学号:
姓名:完成日期: 20xx年x月xx日
五、实验总结
在做本实验之前,自己看了课本上所列举的贪心法解活动安排问题的代码,代码很简单,很容易理解,于是就按课本的代码实现。
通过几个测试用例测试发现结果不对,后来发现自己忘了进行贪心法的一个前提条件,事先没有按各个活动结束时间对所有活动进行非递减排序,所以才会导致结果错误。
经过修正后,自己真正理解了贪心法解活动安排问题的原理,重新完成本次实验内容也是很顺利,在编程方面没有遇到什么困难。