贪心算法介绍
挑选过程是多步判断,每步依据某种“短视”的策略(只看眼前)的策略进行选择,即在每个局部阶段,贪心法都走出一个当前最优的局部决策,并期望通过每次所做的局部最优决策产生一个全局最优解。选择时注意满足相容性条件。
贪心算法类似于分治算法和动态规划,也是一种基于子问题思想的策略。
(分治策略的求解过程是自底向上,但是贪心算法的求解过程是自顶向下)
贪心算法思想
1)贪心法适用于组合优化问题。
2)求解过程是多步判断过程,最终的判断序列对应于问题的最优解。
3)依据某种“短视的”(只看眼前)贪心选择性质判断,性质好坏决定算法的成败。
4)贪心法必须进行正确性证明。
证明贪心法不正确的技巧:举反例
求解步骤
- 分解,将原问题求解过程划分为连续的若干个决策阶段
2.决策,在每一个阶段依据贪心策略进行贪心决策,得到局部的最优解,并缩小待求解问题的规模。
3.合并,将各个阶段的局部解合并为原问题的一个全局最优解。
优势
算法简单,时间和空间复杂度低,考虑求解问题时,首选算法是贪心算法。
贪心法正确性证明
数学归纳法
适合证明涉及自然数的命题P(n)
归纳基础:证明P(1)为真或P(0)为真
归纳步骤:若对所有的n有P(N)为真,证明P(n+1)为真
例题:贪心算法(新生题)
链接:https://ac.nowcoder.com/acm/problem/214715
来源:牛客网
题目描述
明年就要考研了,我给自己制定了学习科目,
但是我该怎么合理的安排我的学习时才能让一天学习到的内容最多呢?
输入描述:
第一行输入学习科目数:n
之后连续输入n行,每行包括两个数据:科目开始时间和结束时间
n=0表示输入结束,不做处理
输出描述:
输出所能完整学习到的最大科目数
示例
输入
6
8 12
6 11
14 15
16 18
15 20
19 22
0
输出
4
备注:
时间输入为整点,例如:1表示1点,13表示下午一点
题解
这个题是一个贪心算法最基础最经典的例题,根据活动安排改编。
这个题中,我们可以有很多种贪心策略,但并不是每一种都是正确的。比如:
策略1:优先安排开始时间早的学习任务
策略2:优先安排持续时间短的学习任务
策略3:优先安排结束时间早的学习任务
经过简单证明,策略3是一种正确的贪心策略
下面基于策略3来对问题进行求解
第一步:预处理。将活动按照结束时间的升序进行排序。
第二步:选择第一个活动。将结束时间最早的学习任务首先安排。
第三步:贪心后续计算。安排入第一个活动之后,就对接下来排过序的学习任务进行遍历,如果这个学习任务的开始时间晚于当前活动,则加入学习计划。
代码
//LMY
#include <iostream>
#include <algorithm>
using namespace std;
class study
{
public:
int start;
int end;
};
int compare(study c, study d)
{
return c.end < d.end;
}
int main()
{
study a[50000];
int n, i, sum = 1, tim;
cin >> n;
for (i = 0; i < n; i++)
cin >> a[i].start >> a[i].end;
sort(a, a + n, compare);
tim = a[0].end;
for (i = 1; i < n; i++)
{
if (a[i].start >= tim)
{
sum++;
tim = a[i].end;
}
}
cout << sum << endl;
return 0;
}