区间覆盖
数轴上有 n 个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1, t];不可能办到输出-1。
输入第一行:N和T
第二行至N+1行: 每一行一个闭区间
输出选择的区间的数目,不可能办到输出-1
sample input:
3 10
1 7
3 6
6 10
sample output:
2
思路:
- 对于每一头牛的区间都有起始时间和结束时间,所以创建结构体用来存储每一头牛的时间区间;由于要进行贪心必须先对时间进行排序,所以需要重写操作符或者重写比较函数,重写操作符在G++11上可能会出现CE错误,可以根据自己的编译环境选择。
- 由于指定线段从1开始,所以在排序之后第一个区间肯定是从1开始的,他也是必须要取到的,所以在初始化定义的时候可以直接将begin和ans定义为1;
- 依次遍历所有的区间,如果当前区间的起始点比现有的起始点小,证明当前的区间覆盖起始点,为了寻找尽量少的区间,要选取更大的终点作为新的终点,也就是说要选取更长的一条
- 若遍历过程中发现当前的区间起始点比现在的起点要大,那么就要判断当前的区间起点能否和现在的结尾接上,如果接不上说明错误,数轴中间有空白没有办法用区间进行覆盖;如果能接上则选择两个中最大的终点进行更新。
- 结束条件为更新后的终点超过给定线段的右端点,说明能完全覆盖。
- 注意:本题要求是整点覆盖,也就是说区间[1,3]和[4,7]是可以覆盖闭区间[1,7]的。体现在代码中设置新的起始点时begin=end+1
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
struct cow
{
int begin;
int end;
// operator < (const cow &c) const
// {
// if(begin!=c.begin)
// return (begin< c.begin);
// else return end > c.end;
// }
};
bool cmp(cow a, cow b)
{
if(a.begin!=b.begin) return a.begin<b.begin;
else return a.end>b.end;
}
int main()
{
int n=0,t=0;
cin>>n>>t;
cow m[n];
for(int i=0;i<n;i++)
{
cin>>m[i].begin>>m[i].end;
}
// sort(m,m+n);
sort(m,m+n,cmp);
int begin=1,end=1;
int ans=1;
for(int i=0;i<n;i++)
{
int tempb=m[i].begin;
int tempe=m[i].end;
if(i==0&&tempb>1) break;//第一段时间(0)必须从1开始
if(tempb<=begin)//当前区间覆盖起始点
end=max(tempe,end);//那么终点就是包括起点的最长线段的终点
if(tempb>begin)
{
ans++;
begin=end+1;//重新设置起始点
if(tempb<=begin)
end=max(tempe,end);
else break;
}
else if(end>=t)//超过范围
break;
}
if(end<t) cout<<"-1"<<endl;
else cout<<ans<<endl;
return 0;
}