1.贪心算法:贪心算法是通过一系列选择找到最优解,每一个决策点都是做一个在当时看来最优的选择,所以贪心算法不一定总是能找到最优解,但通常可以找到最优解。(敝人理解,找到局部最优解而非全局最优解)。
2.适用于贪心算法问题具有的特点:
贪心选择性质:一个全局最优解可以通过贪心选择来表达。
最优子结构:一个问题的最优解也包含了它的子问题的最优解。
(一个问题是否具备这两个性质,都可以通过证明得到,在下不精于此道,就不证明了啊)
3.贪心算法解题基本步骤:
首先,从问题的一个初始解出发;
然后,采用循环,当可以向最终求解目标前进一步时,采用局部最优策略,得到一个部分解。缩小问题的范围或规模;
最后,综合所有部分解,得到最终解。
下面举几个栗子(好吃啊好吃)
4.活动安排问题
假设有一个资源(比如教室),有n个活动竞争使用,其中一个活动如果竞争成功则将占用该资源[si,fi)时间段,si为活动i开始的时间,fi为活动i结束的时间。如果两个活动i和j,si>fj或sj>fi(即两个活动发生的时间没有重叠),则称活动i,j兼容。活动安排问题就是选择一个由兼容活动组成的最大集合。
首先将所有活动,按照fi非递减的顺序排列
排好序后,按照编号由小到大,选择符合兼容条件的加入集合。最后这个集合为{1,4,8,11}
void GreedySelector(T s[],T f[],bool A[],int n)
{ //f[]为排好序的数组
A[0] = true;
int i,j=0;
for(i=1;i<n,i++)
{
if(s[i]<f[j])
{
A[i]=true;
j=i;
}
else
A[i] = false;
}
}
再贴一个完整可编译代码(较复杂,大概看看)
* 主题:活动安排问题
* 作者:chinazhangjie
* 邮箱:chinajiezhang@gmail.com
* 开发语言:C++
* 开发环境:Microsoft Visual Studio
* 时间: 2010.11.21
*/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std ;
struct ActivityTime
{
public:
ActivityTime (int nStart, int nEnd)
: m_nStart (nStart), m_nEnd (nEnd)
{ }
ActivityTime ()
: m_nStart (0), m_nEnd (0)
{ }
friend
bool operator < (const ActivityTime& lth, const ActivityTime& rth)
{
return lth.m_nEnd < lth.m_nEnd ;
}
public:
int m_nStart ;
int m_nEnd ;
} ;
class ActivityArrange
{
public:
ActivityArrange (const vector<ActivityTime>& vTimeList)
{
m_vTimeList = vTimeList ;
m_nCount = vTimeList.size () ;
m_bvSelectFlag.resize (m_nCount, false) ;
}
// 活动安排
void greedySelector ()
{
__sortTime () ;
// 第一个活动一定入内
m_bvSelectFlag[0] = true ;
int j = 0 ;
for (int i = 1; i < m_nCount ; ++ i) {
if (m_vTimeList[i].m_nStart > m_vTimeList[j].m_nEnd) {
m_bvSelectFlag[i] = true ;
j = i ;
}
}
copy (m_bvSelectFlag.begin(), m_bvSelectFlag.end() ,ostream_iterator<bool> (cout, " "));
cout << endl ;
}
private:
// 按照活动结束时间非递减排序
void __sortTime ()
{
sort (m_vTimeList.begin(), m_vTimeList.end()) ;
for (vector<ActivityTime>::iterator ite = m_vTimeList.begin() ;
ite != m_vTimeList.end() ;
++ ite) {
cout << ite->m_nStart << ", "<< ite ->m_nEnd << endl ;
}
}
private:
vector<ActivityTime> m_vTimeList ; // 活动时间安排列表
vector<bool> m_bvSelectFlag ;// 是否安排活动标志
int m_nCount ; // 总活动个数
} ;
int main()
{
vector<ActivityTime> vActiTimeList ;
vActiTimeList.push_back (ActivityTime(1, 4)) ;
vActiTimeList.push_back (ActivityTime(3, 5)) ;
vActiTimeList.push_back (ActivityTime(0, 6)) ;
vActiTimeList.push_back (ActivityTime(5, 7)) ;
vActiTimeList.push_back (ActivityTime(3, 8)) ;
vActiTimeList.push_back (ActivityTime(5, 9)) ;
vActiTimeList.push_back (ActivityTime(6, 10)) ;
vActiTimeList.push_back (ActivityTime(8, 11)) ;
vActiTimeList.push_back (ActivityTime(8, 12)) ;
vActiTimeList.push_back (ActivityTime(2, 13)) ;
vActiTimeList.push_back (ActivityTime(12, 14)) ;
ActivityArrange aa (vActiTimeList) ;
aa.greedySelector () ;
return 0 ;
}
这篇先到这儿,贪心算法未完待续。。。