算法1-4 凌乱的yyy / 线段覆盖
题目描述
现在各大 oj 上有 n 个比赛,每个比赛的开始、结束的时间点是知道的。
yyy 认为,参加越多的比赛,noip 就能考的越好(假的)。
所以,他想知道他最多能参加几个比赛。
由于 yyy 是蒟蒻,如果要参加一个比赛必须善始善终,而且不能同时参加 2 个及以上的比赛。
输入格式
第一行是一个整数 n,接下来 n 行每行是 2 个整数 ai,bi (ai<bi),表示比赛开始、结束的时间。
输出格式
一个整数最多参加的比赛数目。
输入输出样例
输入 #1
3 0 2 2 4 1 3
输出 #1
2
说明/提示
- 对于 20% 的数据,n≤10;
- 对于 50% 的数据,n≤103;
- 对于 70% 的数据,n≤105;
- 对于 100% 的数据,1≤n≤106,0≤ai<bi≤106。
在一个数轴上有n条线段,现要选取其中k条线段使得这k条线段两两没有重合部分,问最大的k为多少。
最左边的线段放什么最好?
显然放右端点最靠左的线段最好,从左向右放,右端点越小妨碍越少
其他线段放置按右端点排序,贪心放置线段,即能放就放。
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int ans=1;
int last_end_time; //上一场比赛结束的时间 C++ 标准库中有个 time 函数,这里不能取time
struct match{
int begin; //比赛开始时间
int end; //比赛结束时间
}m[1000010];
bool cmp(match x, match y)
{
return x.end < y.end;
}
int main()
{
cin>>n;
for(int i=0; i<=n-1; ++i)
{
cin>>m[i].begin;
cin>>m[i].end;
}
//按照比赛结束的早晚排序 结束的早的放在前
sort(m, m+n, cmp);
//结束最早的那场比赛一定可以参加
last_end_time = m[0].end;
//从第二个比赛开始找
for(int i=1; i<=n-1; ++i)
{
//当前比赛的开始时间大于等于上场比赛的结束时间
if(m[i].begin >= last_end_time)
{
ans++;
last_end_time = m[i].end;
}
}
cout<<ans;
return 0;
}