题意
数轴上有 n (1<=n<=25000)个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1, t]( 1<=t<=1,000,000)。
覆盖整点,即
(1,2)+(3,4)
可以覆盖(1,4)
!!!!!!。’
刚开始以为只有(1,2)+(2,4) 才可以覆盖(1,4),导致一直WA;
不可能办到输出-1
Input
第一行:N和T
第二行至N+1行: 每一行一个闭区间。
Output
选择的区间的数目,不可能办到输出-1
Sample Input
3 10
1 7
3 6
6 10
Sample Output
2
思路
每次查找可以尽量可能大的覆盖区间的区间,直到全部区间被覆盖。
过程
首先将所有区间按左端点排序,然后选择尽可能大的区间来覆盖总区间,然后再从剩下的区间里面,选择下一个尽可能大的能覆盖剩下总区间的区间,继续下去,直到覆盖整个总区间。
代码
//这道题输入数据很多,请用scanf而不是cin cin读入比scanf慢
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
struct section
{//存储的区间
int l;
int r;
};
bool cmp(const section a,const section b)
{//比较区间的左端点
return a.l<b.l;
}
section ans[25000]; //存储区间
int main(int argc, char** argv)
{
int N,T;
int count;
while(scanf("%d %d",&N,&T)!=EOF) //读到数据尾为止
{
for(int i=0; i<N; i++)
{
scanf("%d %d",&ans[i].l,&ans[i].r); //读入数据
}
sort(ans,ans+N,cmp); //按左端点排序
if(ans[0].l>1)
{//相当于剪枝
//如果按左端点升序排序 第一个最小左端点 不是1 那么则无法覆盖从1到T
printf("-1\n");
continue;
}
count=0;//选取区间个数
int index=0,new_r=1,new_rr=0;
//index 区间索引 new_r 当前所在右端点 new_rr当前可到达最右端点
while(new_rr<T)
{//可到达的最右端点达不到T的时候 执行函数
for(;index<N;index++)
{//遍历区间
if(ans[index].l<=new_r&&ans[index].r>=new_r)
{//新的区间的做端点不能大于当前最右端点 刚开始是1 后面是new_rr+1
if(ans[index].r>new_rr)
{//寻找可以到达的最右端点
new_rr=ans[index].r;
}
}
else if(ans[index].l>new_r)
{//左端点超过了当前的右端点 结束遍历
break;
}
}
if(new_rr<new_r) break; //所能到达的右端点不会在增加 就结束寻找
else
{//加一个区间 并更新当前可以到达的右端点 为new_rr+1 这样才能保证
//(1,2)+(3,4)可以覆盖(1,4);
count++;
new_r=new_rr+1;
}
}
if(new_rr>=T) printf("%d\n",count); //可以覆盖T
else
{//不能
printf("-1\n");
}
}
return 0;
}
总结
注意细节!!!!!
覆盖整点,即
(1,2)+(3,4)
可以覆盖(1,4)
!!!!!!。’
刚开始以为只有(1,2)+(2,4) 才可以覆盖(1,4),导致一直WA;