ACM入门算法(一)贪心算法
贪心算法
引例:
学校的小礼堂每天都会有许多活动,有时间这些活动的计划时间会发生冲突,需要选择出一些活动进行举办。小刘的工作就是安排学校小礼堂的活动,小礼堂只有上午,下午和晚上三个时间段能安排活动,每个时间段最多安排一个活动,每个活动可能占用多个时间段。为了方便,小刘按时间表顺序把所有时间段分别编号为1,2,3,4…,现在给你一些活动计划的时间表,小刘想尽可能的安排更多的活动,请问他该如何安排。
如:活动1:3号时间段到10号时间段(包括10号时间段,下同)
活动2:4号时间段到6号时间段
活动3:7号时间段到15号时间段
活动4:1号时间段到5号时间段
活动5:2号时间段到3号时间段
小刘应该选择:活动2,活动3,活动5
思路:
做这道题目的时候,我们先来想一下下面的情况:如果有两个活动让你选择一个,它们的结束时间一前一后,那么,我们应该选择哪一个才能有利于之后选取更多的活动呢?
很明显,我们应该选择的是结束时间较早的那个活动。
同样,在有一大堆活动时,我们最先应该选择结束时间最早的那个,以利于之后能安排更多的活动,然后,再在剩下的可选的会场中选择最可能结束时间最早的那个,依次类推,直到无法安排任何活动为止。
也就是说,每次选择时,都应该贪婪的选择结束时间最短的那个活动。
现在我们来证明刚才的贪心方法是正确的:假设有哪一次选择的不是结束时间最早的那个活动,那么,此次选择之后,剩下的可选活动一定没有选择结束时间最早的活动时多,用这种方法之后可再选择的活动数目一定不会比上面思路中的方法更多。
代码提示:
这道贪心算法的题目里用到了排序,排序是一种极为常见的操作,在C语言的库函数里有qsort函数来实现快速排序,C++标准库里也有sort算法来实现排序,关于sort的用法,在本节补充材料里有详细讲解。
引例显示出了贪心算法的特性:每次选择都选择当前认为的最优解。全局的最优解是建立一次次的求出局部最优解而得出的。
但是,有时候,我们当前认为是好的东西,未必真的就好。同样,有些时候,使用贪心算法可能会得到错误的结果。这就要求我们使用贪心算法必须要小心证明其正确性。
材料一、排序算法
排序在程序设计中是一种极为常见的操作,因此,我们必须掌握sort算法。
在C++STL里,sort一般需要两个参数,如:
int arr[10]={5,4,1,9,6,4,11,2,4,7};//声明一个10个元素的数组
sort(arr,arr+10); //将[arr,arr+10)区间内的所有元素按升序排序
执行了上面的操作之后,arr数组里的元素就是:
1 2 4 4 4 5 6 7 9 11
那么,请大家思考arr数组按以下各个操作后包含的内容是什么:
1) sort(arr,arr+2);
2) sort(arr+3,arr+4);
另外,如果想指定排序的规则,可以由第三个参数来指定:
比如,sort(arr,arr+10,greater
sort的第三个参数还可以是其它的一些类型,比如传入一个函数。
比如,想要让一些数,按照其个位数的大小升序排序,可以先写一个函数:
bool numless(int num1,int num2)
{
return num1%10 } 然后,再将numless传入sort函数做为第三个参数: sort(arr,arr+10,numless); sort函数的用法还有许多东西可以讲,但这里只是给大家做一个了解,详细的知识,请参阅C++STL的专门书籍。