有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿。请在给出的喷水装置中选择尽量少的喷水装置,把整个草坪全部润湿。
-
输入
-
第一行输入一个正整数N表示共有n次测试数据。
每一组测试数据的第一行有三个整数n,w,h,n表示共有n个喷水装置,w表示草坪的横向长度,h表示草坪的纵向长度。
随后的n行,都有两个整数xi和ri,xi表示第i个喷水装置的的横坐标(最左边为0),ri表示该喷水装置能覆盖的圆的半径。
输出
-
每组测试数据输出一个正整数,表示共需要多少个喷水装置,每个输出单独占一行。
如果不存在一种能够把整个草坪湿润的方案,请输出0。
样例输入
-
2 2 8 6 1 1 4 5 2 10 6 4 5 6 5
样例输出
1
2
#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
struct mb{
double left,right;
}s[1001]; //排序用到的结构体
int max(double x,double y)
{
if(x>y)
return x;
return y;
} //比较大小
int cmp(mb x,mb y)
{
return x.left<y.left; //快排
}
int main()
{
int n;
double c,d,temp;
scanf("%d",&n);
while(n--)
{
int t,i=0;
double w,h;
scanf("%d %lf %lf",&t,&w,&h);
int T=t;
while(T--)
{
scanf("%lf %lf",&c,&d);
if(d*2<=h)
temp=0;
else
temp=sqrt(pow(d,2)-pow(h/2,2)); //预处理 ,计算装置喷水之后的范围,利用区间来找
s[i].left=c-temp; //左边范围
s[i].right=c+temp; //右边范围
i++;
}
sort(s,s+t,cmp); //快排
int sum=0;
double start=0,p=0; //start从0开始
for(i=0;i<t;i++)
{
if(s[i].left<=start)
{
p=s[i].right;
while(s[i].left<=start) //从start开始寻找符合条件的右边最大范围
{
p=max(p,s[i].right);
i++;
if(i==t)
break;
}
start=p; //更改左边范围
i--;
sum++; //计数器
}
if(start>=w) //如果超过了总宽度,就结束
break;
}
if(start>=w)
printf("%d\n",sum);
else //如果最后的右边范围没达到总宽度,就输出0
printf("0\n",start);
}
return 0;
}