您的位置:首页 > 编程语言 > Go语言

贪心算法(Greedy Algorithm)之活动选择问题(Activity-Selection Problem)

2009-03-18 13:39 387 查看
活动选择问题是《算法导论》里面关于贪心算法的第一个问题。这个问题是这样的。我们有一组活动,每个活动都有一个开始时间Si和结束时间Fi。如下图:



每个活动都共享同一个公共的资源(比如教室等)所以同一时间只能有一个活动。现在的问题就是要在指定的时间内让举办的活动数量做大。

这个问题是贪心算法一个典型的应用。说到贪心,贪心基本解决问题的方案就是

#1.尽可能在局部找到一个最优的解

#2然后证明这个局部的优化解是全局优化解的一部分

#3最后把这个局部解用递归或者迭代的方式推广到全局。

所谓贪心,一般都会把带选择的资源做个权重的排序,每次的最优化子结构的选取其实就是最大权重的选取。就这个活动选择问题而言,我们将所有的活动结束时间排序。这里的局部最优解就是指到特定的时间Fi为止的最优解。这个最优解的贪心意义体现在每次最优解利用了最早结束时间,从而是剩余时间最大化。

// Activity_Selection.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <vector>
#include <functional>
#include <algorithm>
#include <iostream>
struct activity
{
int s;
int f;
};
struct activitySort: public std::binary_function <activity, activity, bool>
{
bool operator()(const activity& a1, const activity& a2)
{
return a1.f < a2.f ;
}
};
struct activityPrint {
void operator() (activity a)
{
std::cout<< "s = "<<a.s <<" , f = "<<a.f <<std::endl;;
}
};
/**
* Description: find the max activity count in a particular time
*			   and print the result
*@param a, un-sorted activity set;
*/
void activity_selector( const std::vector<activity>& av)
{
std::vector<activity> A;
// create one copy since the parameter is const
std::vector<activity> a(av);
std::sort( a.begin(), a.end(), activitySort() );
A.push_back(a[0]);
int j= 0;
for (int i=1;i<a.size();i++)
{
if ( a[i].s >= a[j].f )
{
A.push_back(a[i]);
j = i;
}
}
std::for_each(A.begin(), A.end(), activityPrint());
}
int _tmain(int argc, _TCHAR* argv[])
{
//	Activity k[] = { {1,4}, {3,5}, {0,6}, {5,7}, {3,8}, {5,9}, {6,10}, {8,11}, {8,12}, {2,11}, {12, 14} };

// un-sorted
activity k[] = { {0,6}, {1,4}, {2,11}, {3,5}, {3,8}, {5,7}, {5,9}, {6,10}, {8,11}, {8,12}, {12, 14} };
std::vector<activity> av ( k, k + sizeof(k)/sizeof(k[0]) );
activity_selector(av);
system("pause");

return 0;
}


以上的activity_selector函数就是这样的一个迭代的解。在迭代的过程中,每次都保留一个最近选择活动的index,或者说最近活动的结束时间。用来给后面的活动做比较。(这里的函数实现的不是很妥当,我加入了一些debug信息什么的。)

需要注意的事情是,这个算法非常高效。仅用O(n)的时间就可以找到解决方案。如果动态规划的话。下面就是他的递归式:



简单地说就是从活动i到j的选择策略就是i-k和k-j的最大策略加1。这个表达式不由让我们想起了矩阵链乘的O(n^3)复杂度.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: