C题 区间覆盖
题目描述
数轴上有 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
解题思路
定义一个结构体,来存储这样的区间
struct Node{
int beg,end;
}node[maxn];
这道题典型贪心算法来解决,分析一下:
我们将这些区间按左端点从小到大排列起来,然后我们开始寻找能覆盖[1,t]的线段,那么这样可以有两个判出条件
1.选择的线段比所有线段多
2.所能到达的最远端是否达到t
如果把这部分思路贪心一下,就可以再变成,当我们在选择下一条线段时,下一条线段的开始一定要比现在已经到达的最远点要小(这样才能完全覆盖)则我们把当前所选线段的远端作为起点继续循环,如果比当前所到达的最远点大时,则发生了断开,不能完全覆盖……这样循环就能得出答案,结合刚才的判出条件就能解决啦
注意事项:[1,2],[3,4]能覆盖[1,4],所以再不断更新开始的头时,注意要加一
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=25010;
struct Node{
int beg,end;
}node[maxn];
bool cmp(const Node &a,const Node &b)
{
return a.beg<b.beg;
}
int main()
{
int n,s;
scanf("%d %d",&n,&s);
// Node node[maxn];
for(int i=0;i<n;i++)
scanf("%d %d",&node[i].beg,&node[i].end);
sort(node,node+n,cmp);
// start: 第一个没被覆盖的位置
int ans = 0, start = 1, pos = 0, ok = 0;
while(start<=s)
{
int maxl = 0, k = 0;
while(pos <= n)
{
if(node[pos].beg <= start)
{
maxl = max(maxl, node[pos].end);
pos++;
}
else break;
}
if(maxl < start)
{
ok = 1;
break;
}
start = maxl + 1;
ans++;
}
if(ok==0) cout<<ans;
else cout<<"-1";
return 0;
}