题意:
数轴上有 n (1<=n<=25000)个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1, t]( 1<=t<=1,000,000)。
覆盖整点,即(1,2)+(3,4)可以覆盖(1,4)。
不可能办到输出-1
输入
第一行:N和T
第二行至N+1行: 每一行一个闭区间。
思路:
运用贪心策略求解,贪心的准则是:选择一条可以覆盖到线段的并且长度最大的区间。将区间按照左端点left升序排序,如果left相同则按照right排序,初始化时设置一个rightlength,来标记初始区间的右端点,设置一个maxlength来标记新的区间的右端点到rightlength的最大距离,遍历排序好的区间数组,新的区间无非两种情况:
1、左端点left在rightlength之前,表示新的区间与被选入的区间有交集 ,选择出有交集的区间最长的一条
2、左端点left在rightlength之后,表示新的区间与被选入的区间没有交集,覆盖失败
对于有交集的区间,这时计算它的右端点right到rightlength的长度是否大于maxlength,如果大于则证明找到了一个可以延伸的区间,更新最大长度maxlength,当把与被选入的区间有交集的新区间全部遍历完毕时,就可以选择出长度最大的区间temp,最后rightlength更新为新的右端点。
总结:
这个问题犯错在,当一个新的区间的左端点在标记的右端点之前,表示有交集时,少考虑了区间包含的情况,比如(1,9) (2,3),导致判断为没有覆盖到,输出了-1。
运用贪心策略时,需要找好贪心的指标,选择出一个最优的解决方案,用最优的方案求出解,而这个求最优的解决方案需要多次考虑,判断出区间的各种情况:有交集、无交集,并且在有交集的区间中选择最长的。
代码:
#include <stdio.h>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
struct qvjian
{
int left;
int right;
qvjian(int _l,int _r)
{
left = _l;
right = _r;
}
qvjian() {}
inline bool friend operator<(const qvjian &a,const qvjian &b)
{
if (a.left != b.left)
{
return a.left < b.left;
}
else
{
return a.right < b.right;
}
}
}test[25000];
int main()
{
int N,T;
int size = 0;
scanf("%d%d",&N,&T);
for (int i = 0; i < N; i++)//预处理 先去除掉完全不符合的区间
{
int l,r;
scanf("%d%d",&l,&r);
if (l >=1 && l <= T)
{
test[i].left = l;
test[i].right = r;
size++;
}
}
sort(test,test+size);
if (test[0].left != 1)
{
printf("-1");
}
else
{
int ans = 1;
int rightlength = test[0].right;
int temp = 0;
int maxlength = 0;
int find = 0;
for (int i = 1; i < size; i++)
{
find = 0;
if (rightlength >= T)
{
break;
}
while (i < size && test[i].left <= rightlength + 1)
{ //当区间的左端点没超过 设置的右端点时,判断长度
if (maxlength < (test[i].right - rightlength))
{//该点到rightlength的距离超过了最大距离 更新
maxlength = test[i].right - rightlength;
temp = i;//记录下最大距离的点
find = 1;
i++;
}
else//没找到的情况 包含
{
find = 1;
i++;
}
}
if (find == 1)//如果找到了可以覆盖的最长的边 更新右端点
{
rightlength = test[temp].right;
maxlength = 0;
ans++;
i--;
}
if (find == 0)
{
break;
}
}
if (rightlength < T)//已经找完所有的边 未能覆盖 或者 中间出现了断层
printf("-1");
else
printf("%d",ans);
}
return 0;
}