题目描述
有N项工作,每项工作分别在Si时间开始,在Ti时间结束。对于每项工作,你都可以选择参与与否。如果选择了参与,那么自始至终都必须全程参与。此外,参与工作的时间段不能重叠(即使是开始的瞬间和结束的瞬间重叠也是不允许的)。
目标是尽可能参与可能多的工作,那么最多能参与多少项工作?
样例输入
n = 5, s= {1,2,4,6,8}, t={3,5,7,9,10}
样例输出
3 (选取工作1、3、5)
思路分析
贪心算法之所以能用,是基于以“结束时间最早”为前提的。但是这是需要你分析和证明的,你要先想明白为什么 按结束时间最早排序才是正确的。
- 因为结束时间最早,所以取相同数量的工作肯定它最早结束或至少不晚。
- 如果后面还有工作,那么加入到结束最早算法的空间更大。 因此就不会存在比它更多工作的可能。
AC代码
#include <iostream>
#include <algorithm>
using namespace std;
/*
1:每次选取结束时间最早的任务
2:选取T数字最小的时间段
*/
const int MAX_N = 100000;//方便更改更大的值
int N = 5, S[MAX_N] = { 1,2,4,6,8 }, T[MAX_N] = { 3,5,7,9,10 };//输入,S开始时间,T结束时间
pair<int, int> itv[MAX_N];//用于对工作排序的pair数组
void solve()
{
for (int i = 0; i < N; i++)//先把数据存入
{
itv[i].first = T[i];
itv[i].second = S[i];
}
/*
sort:首先根据first进行排序,first数据相同根据second排序【重点(注意sort执行的过程)】
按照由小及大进行排序,即按照结束时间最小进行排序,结束时间相同按照开始时间最小进行排序。
*/
sort(itv, itv + N);
int ans = 0, t = 0;//t是最后所选工作结束的时间
/*
结束时间小于下一个最先结束可执行时间,
*/
for (int i = 0; i < N; i++)
{
if (t < itv[i].second)//判断区间是否重叠
{
ans++;
t = itv[i].first;
}
}
cout << ans << endl;
}
int main() {
solve();
system("pause");
}