贪心法介绍: 一个贪心算法总是做出当前最好的选择,也就是说,它期望通过局部最优选择从而得到全局最优的解决方案。
大体步骤:
- 贪心策略:制定贪心策略,并选择最佳的策略实施
- 局部最优解:通过策略,一步一步得到局部最优解。
- 全局最优解:把所有的局部最优解整合到一起,还原出原来问题的最优解。
示例如下
问题描述
在有限的时间里安排更多的会议进行,任何两个会议不能同时进行。
贪心策略
- 每次从剩下未安排的会议中选择会议具有安排 具有最早开始时间且与已安排的会议相容 的会议安排,以增大时间资源的利用率。
- 每次从剩下未安排的会议中选择会议具有安排 持续时间最短且与已安排的会议相容 的会议安排,以安排更多一些的会议。
- 每次从剩下未安排的会议中选择会议具有安排 具有最早结束时间且与已安排的会议相容 的会议安排,以尽快安排下一场会议。
分析:
策略1中安排最早开始时间,若会议时间长,那么总会议次数必定减少;策略2中安排持续时间最短的,若会议安排时间较晚,则其他会议必定被耽误;那么我们可以选择安排开会较早且会议持续时间较短的会议,即结束时间较早。
所以我们选择策略3:每次从剩下未安排的会议中选择会议具有安排 具有最早结束时间且与已安排的会议相容 的会议安排,以尽快安排下一场会议。
思路
- 将会议开始时间和结束时间存入结构体数组中。
- 按照结束时间排序,若是结束时间相同,按照开始时间先后排序(即结束时间相等,开始时间早的先安排)。
- 依次从未安排的会议中安排会议,下一个会议的开始时间不能超过前面会议的结束时间,否则舍弃该会议,考虑下个会议。
完整代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
struct Meet
{
int num; // 会议编号
int beg; // 会议开始时间
int end; // 会议结束时间
}meet[1000];
bool cmp(Meet a,Meet b)
{
if(a.end == b.end)
{
return a.beg > b.beg;
}
return a.end < b.end;
}
class setMeet
{
public:
void init()
{
int s,e;
cout<<"输入会议总数:"<< endl;
cin>>n;
int i;
cout<<"请输入会议开始时间和结束时间: "<<endl;
for(i=0;i<n;i++)
{
cin>>s>>e;
meet[i].num = (i+1); // 会议编号
meet[i].beg = s; // 会议开始时间
meet[i].end = e; // 会议结束时间
}
}
void solve()
{
sort(meet,meet+n,cmp);
cout<<"排序后的会议时间如下:"<<endl;
int i;
cout << "会议编号" << " 开始时间"<<" 结束时间"<<endl;
for(i = 0;i < n;i++)
{
cout<<" "<<meet[i].num<<"\t\t"<<meet[i].beg<<"\t"<<meet[i].end<<endl;
}
cout<<"----------------------------------------------------------"<<endl;
cout<<"选择的会议的过程:"<<endl;
cout<<"选择第"<<meet[0].num<<"个会议"<<endl;
ans=1;
int last = meet[0].end;
for(i = 1;i<n;i++)
{
if(meet[i].beg >= last)
{
ans++;
last = meet[i].end;
cout<<"选择第"<<meet[i].num<<"个会议"<<endl;
}
}
cout<<"最多安排"<<ans<<"个会议"<<endl;
}
private:
int n,ans; // 会议数量 n; 安排会议总数量 ans
};
int main()
{
setMeet sm;
sm.init();
sm.solve();
return 0;
}