描述
数轴上有 n (1<=n<=25000)个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1, t]( 1<=t<=1,000,000)。
覆盖整点,即(1,2)+(3,4)可以覆盖(1,4)。
不可能办到输出-1
输入
第一行:N和T
第二行至N+1行: 每一行一个闭区间。
输出
选择的区间的数目,不可能办到输出-1
样例输入
3 10
1 7
3 6
6 10
样例输出
2
提示
这道题输入数据很多,请用scanf而不是cin
思路与收获
该题和上一道题类似,但是更复杂一些。
这道题有个突破口,即目标区间的起点是1,意味着我们可以从头往后“赶”,不断解决一个个的子问题。每次遍历都要取能够覆盖前面从起点算起的最大区间。
这道题一个好处在于目标区间从1开始,如果目标区间起点不确定就更复杂了。
#include<algorithm>
#include<cstdio>
using namespace std;
//一开始读题失误了,误以为第一行输入的是目标区间,实际上第一行是区间数和目标区间的终点
//这道题跟上一道题差不多,只是情况比较多,需要细细考虑
//当然,用手画出图形进行循环遍历仍然是很好的获得解题思路的方法
struct node {
int a,b;
bool operator < (const node& y) {
return
(a<y.a)
||
(a==y.a&&b<y.b);
}
};
int main() {
//freopen("inc.txt","r",stdin);
int n,t;
while(~scanf("%d %d",&n,&t)) {
node* a=new node[n];
int sum=0;
bool flag=true;
for(int i=0; i<n; i++) {
scanf("%d %d",&a[i].a, &a[i].b);
}
sort(a,a+n);
int count=1;
//首先进行起点的判断,起点达不到要求直接退出
int next_start=1;//由于此值需要参加最终比较,因此放在外面声明
if(a[0].a>1) {
// printf("-1");
count=-1;
} else {
//使用贪心法,循环地获得下一个小区间,也就是不断求解子问题
int start=1;//每次循环从这里开始,该值不断变化
for(int i=0; i<n; i++) {
//如果当前区间没有覆盖点当前起点,证明覆盖当前起点的区间选择到了最优情况
//开始对下一个起点进行遍历
if(start<a[i].a) {
start=next_start;
//如果当前区间无法覆盖新的当前起点(也就是上一个区间的终点)
//证明这个区间和上一个区间之间存在缝隙,退出
if(next_start<a[i].a) {
count=-1;
break;
}
count++;
}
//如果当前区间可覆盖当前起点,则该区间内部无需遍历
//该区间终点可能作为下一个起点进行遍历
if(start>=a[i].a && start<=a[i].b && next_start<a[i].b+1)
next_start=a[i].b+1;
if(next_start>t)break;//结束条件
}
}
if(next_start<=t)count=-1;
printf("%d\n",count);
delete[] a;
}
return 0;
}