贪心算法:
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。
这部博客有相关介绍:点击打开链接
例题:
之前面试网易时,编程题第三题就是贪心。题目是:有n项工作每项工作分别在Si时间开始,在Ti时间结束。对于每项工作,你都可以选择参与与否。如果选择参与,那么自始至终都必须参与。此外,参与工作的时间段不能重叠。你的目标是参与尽可能多的工作,结果返回最多参与多少项工作。
限制条件: 1<=N<=100000,1<=Si<=Ti<=109。
思路:
首先,给出3种思想,考虑一下用哪个?
(1)在可选的工作中,每次都选择开始时间最早的工作。
(2)在可选的工作中,每次都选择用时最短的工作。
(3)在可选的工作中,每次都选择与最少可选工作有重叠的工作。
(4)在可选的工作中,每次都选择结束时间最早的工作。
下图分别为1,2,3的反例:
所以,正确思路是:先根据工作的结束时间从小到大排序,然后判判断下一个工作的开始时间是否晚于上一个工作的结束时间。(根据结束时间来排序的!只要这个工作能做,绝对是最早结束的)
代码:
#define Max_N 100000
int N,S[Max_N],T[Max_N];
pair<int,int> data[Max_N]; // 一个工作的开始,结束时间为一组
void Solve()
{
for(int i=0;i<N;i++)
{
data[i].first = T[i]; // 按照结结束时间排序,方便起见first用结束时间
data[i].second = S[i];
}
sort(data,data+N); // 排序
int Ans = 0;
int t = 0;
for(int i=0;i<N;i++)
if(t < data[i].second) // 只有t<开始时间才能做该项工作
{
Ans++;
t = data[i].first; // t换为该项工作的结束时间
}
printf("%d\n",Ans);
}
结果:
选择的是(1,3),(4,7),(8,10)三项工作。
一直向前,贪心~
(刚开始写博客,主要是为了保存一些东西,也分享一些自己的心得,有错误希望指出)