贪心算法
前言
- 贪心算法总是做出在当前看来是最好的选择。
- 也就是说,贪心算法并不是从整体最优上加以考虑,它所做出的选择只是某种意义上的局部最优选择。
- 当然,我们希望贪心算法得到的最终结果也是整体最优的。
- 具有最优子结构性质的问题,可以用动态规划算法来解决,但是用贪心算法更简单,更直接且解题效率更高。
- 总结:问题逐步求解时,每一步做最优选择。
- 即使贪心算法不能得到整体最优解,但其最终结果却是最优解的很好的近似解。
一、活动安排问题
1.问题描述
该问题要求高效地安排一系列争用某一个公共资源的活动。
有𝒏个活动,开始和结束的时间𝒔_𝒊≤𝒇_𝒊,如何安排最多个活动?
贪心策略:按结束时间递增排序,从前向后能安排则安排
2.例 当前有4个活动
3.程序实现
程序4_1
//4_1 P91
template <class Type>//模板类
void GreedySelector(int n, Type s[],Type f[],bool A[])//n活动个数,s开始时间,f结束时间,A活动是否被选中,运行前已对f进行排序
{
A[1]=true;//选入第1个活动,是必选
int j=1;//j记入选入活动的编号,初始值1
for(int i=2;i<=n;i++)//依次检查第2到n个活动
{
if(s[i]>=f[j])//后一个活动的开始时间晚于前一个活动的结束时间,则选入
{
A[i]=true;
j=i;//j记入选入活动的编号
}
else
A[i]=false;//i开始在j结束前,放弃
}
}
推广
贪心策略思路1:
先在第1会场安排最多活动,其次在第2会场安排最多,……,依次类推。
程序见4_2.cpp
考察运行结果
程序4_2
//会场安排问题推广
#include <iostream.h>
template <class T>
bool GS1(int n,T s[],T f[],int A[],int k)//有n个活动,s[]活动开始时间,f[]活动结束时间,A[]记录活动被分配的会场
//A[i]=k表示活动i分配到会场k;分配结束返回false,否则返回true,继续
//bool GS1(int n,int s[],int f[],int A[],int k)
{
int j=1;//j记录活动
while(A[j])//A[]记录活动被分配的会场,初始均为0,若非0则表明已分配到会场,考察下一个
j++;
if(j>n)
return false;
else
A[j]=k;//若j>n表示n个活动都分配了会场,否则为活动j分配会场
for(int i=j+1;i<=n;i++)
{
if(!A[i])//若活动i没有被分配会场
{
if(s[i]