Title:数轴上有 n (1<=n<=25000)个闭区间 [xi, yi],选择尽量少的区间覆盖一条指定线段 [1, t]( 1<=t<=1,000,000)。覆盖整点,即(1,2)+(3,4)可以覆盖(1,4)。不可能办到输出-1
Input:
第一行:N和T
第二行至N+1行: 每一行一个闭区间。
Output:
选择的区间的数目,不可能办到输出-1
样例:
Input:
3 10
1 7
3 6
6 10
Output:
2
分析:
- 清除掉那些在线段[s,t]之外的区间,减少处理的区间量
- 去除掉具有包含关系的小区间,同样也是减少处理的区间量
- 对区间进行排序,按照x从小到大的顺序
- 排序后,若第一个区间的x不等于s,说明不可能覆盖s点,也就是不可能覆盖这条指定的线段
- 选择起点等于s的最长的一个区间max,进行覆盖。下一次选择区间时,起点应该置为max.y+1,选择起点小于等于max.y+1的最长区间,依此类推。直到将线段完全覆盖。
//now表示的是上一次已经覆盖到的最大点
//置起点now=s-1,即为起点的前一个点
while(now<t)
{
now++;//这一次进行覆盖需要从now的下一个点开始
找到起点小于等于now的最长区间max;
if(没有找到) 说明覆盖失败,退出;
覆盖所用区间数++;
now=max区间的y;
}
总结:假如覆盖到4,那么下一次应该是从5开始覆盖。[3,4],[5,6]是可以覆盖到[3,6]的。故每次选取区间[x,y]进行覆盖后,下一次覆盖应该从y+1开始。
备注:原题是将一天分成T个时间段,用1~T对时间段进行编号,给定n个区间进行覆盖。在此情境下,不会出现[1,T]之外的区间,故代码中并没有进行清除[1,T]之外的区间,也没有去掉具有包含关系的小区间。
#include<stdio.h>
#include<algorithm>
using namespace std;
#define range 25000
struct interval
{
int x;
int y;
};
int N = 0, T = 0, index = 0;
interval a[range];
bool com(const interval& a, const interval& b)
{
return a.x<b.x;
}
int func()
{
int i=0,now=0,max=0,number=0,maxi=0;
while(now<T)
{
now++;
max=now;
maxi=-1;
for(;i<N;i++)//找最长
{
if(a[i].x<=now)
{
if(a[i].y>=max)
{max=a[i].y;
maxi=i;
}
}
else break;
}
if(maxi== -1)
return -1;
number++;
now=a[maxi].y;
}
return number;
}
int main()
{
while (scanf("%d %d",&N,&T)!=EOF)
{
index=0;
while (index < N)
{
scanf("%d %d",&a[index].x,&a[index].y);
index++;
}
sort(a, a + N, com);
if (a[0].x != 1)
printf("-1\n");
else
{
int number=func();
if(number==-1)
printf("-1\n");
else printf("%d\n",number);
}
}
return 0;
}