题目:
数轴上有 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
思路:
这题依旧是贪心算法。这一题的策略为:先将所有区间按左端点大小排列,若左端点相同,则按长度从大到小排列。尽可能排除掉和线段无交集的区间(若排除方法巧妙可减小复杂度)。按照已排好的序,从最小开始,寻找左端点小于等于线段端点且与线段相交长度最大的区间,找到后计数器加一,将线段减去与已选区间交集部分,继续执行上述步骤直到线段长度为0。执行完毕后计数器内内容就是所需数字。值得注意的是,这里还可加个特判来直接判断不可能覆盖线段的情况,并且排除掉与线段无交集的区间时,若不注意排除方法,可能会增大程序复杂度。
代码:
#include <stdio.h>
#include <algorithm>
#include <queue>
using namespace std;
struct section
{
int low;
int high;
bool operator <(const section &s)
{
if(low==s.low)
return (high-low)>(s.high-s.low);
else
return low<s.low;
}
};
queue<section> q;
section s[26000];
int main()
{
int n,t;
//cin>>n>>t;
scanf("%d %d",&n,&t);
int olow=1;
int ohigh=t;
for(int i=0;i<n;i++)
{
//section tmp;
//cin>>tmp.low>>tmp.high;
scanf("%d %d",&s[i].low,&s[i].high);
//q.push(tmp);
}
sort(s,s+n);
int needle=0;
int count=0;
while(1)
{
int max=0;
int maxid=0;
if(s[needle].low>olow||needle>=n)
{
//cout<<"-1";
printf("-1");
return 0;
}
int i;
for(i=needle;s[i].low<=olow&&i<n;i++)
{
if((s[i].high-olow+1)>max)
{
max=s[i].high-olow+1;
maxid=i;
}
}
olow=s[maxid].high+1;
count++;
if(olow>ohigh)
{
//cout<<count;
printf("%d",count);
return 0;
}
while(s[needle].high<olow&&needle<n)
needle++;
}
}