贪心算法极速入门

在《算法导论》中,讲到高级算法的时候,认为主要有三类,即:动态规划、贪心算法和平摊分析。这里通过一个经典小例子介绍一下贪心算法,可以让我们极速掌握贪心算法的思想。

例:活动安排问题

n n n个需要在同一天使用同一个教室的活动 a 1 a_1 a1, a 2 a_2 a2, ⋯ \cdots , a n a_n an,教室同一时刻只能由一个活动使用。每个活动 a i a_i ai都有一个开始时间 s i s_i si和结束时间 f i f_i fi 。一旦被选择后,活动 a i a_i ai就占据半开时间区间 [ s i , f i ) [s_i, f_i) [si,fi)。如果 [ s i , f i ] [s_i,f_i] [si,fi] [ s j , f j ] [s_j,f_j] [sj,fj]互不重叠, a i a_i ai a j a_j aj两个活动就可以被安排在这一天。这时也称这两个活动是相容的。该问题就是要安排这些活动使得尽量多的活动能不冲突的举行。例如下图所示的活动集合 A = { a 1 , a 2 , ⋯   , a n } A=\{a_1, a_2, \cdots, a_n\} A={a1,a2,,an},其中各项活动按照结束时间单调递增排序

图片: 活动安排时间表
贪心算法极速入门_第1张图片
解题思路:
首先,把各项活动按结束时间单调递增排序。这样做是有道理的,因为可以用数学归纳法证明,用贪心算法求解的时候,最先结束的那个活动一定在解集里面。具体证明方法在《算法导论》里有,这里略过不提。其实在直观上也比较好理解,选择了最早结束的那个活动,可以为未安排的活动留下尽可能多的时间。

其次,我们来考虑贪心策略。上面说过,第一个活动已经选出来了,就是最早结束的那个活动 a 1 a_1 a1。那么第二个活动不妨就选跟它兼容的最先开始的活动就行了这个例子中就是 a 4 a_4 a4,因为 s 4 > f 1 s_4>f_1 s4>f1。同理,下一个活动的选取,只要是开始时间大于 f 4 f_4 f4的最近的一个就行了,依次类推。这就是贪心的策略,每次都选最近的。

以下是源程序:

#include
using namespace std;

int Greedy(int len, int *s, int *f, bool *flag) 
{
	int i=0;
	for(int j=1; j= f[i]) 
		{
			flag[j] = true;
			i = j;
		}
	}
	return 0;
}


int main() 
{
	int s[11] = {1, 3, 0, 5, 3, 5, 6, 8, 8, 2, 12};
	int f[11] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
	bool flag[11] = {false};
	flag[0] = true;                 //由于排序后,第一个活动肯定能被选中,所以将它的标志置为"真"。
	
	Greedy(11, s, f, flag);
	
	for(int i=0; i<11; i++)
	{
		if(flag[i])
		{
			cout<

在这段程序中,我们用flag[11]来标记每个活动是否被选中。程序运行结果为:1 4 8 11

你可能感兴趣的:(C++专区)