题目描述
有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=100000)个点状的喷水装置,每个喷水装置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<bits/stdc++.h>
using namespace std;
struct node{
double l,r;
}a[100005];
bool cmp(node x,node y){ return x.l<y.l; }
int N,n,w,h,num;
int main(){
cin>>N;
while(N--){//列 行
cin>>n>> w>>h;
double H=h/2.0;
int x,r;
num=0;
for(int i=1;i<=n;i++) {
cin>>x>>r;
if(r>H){
double t=sqrt(r*r-H*H);
a[++num].l=x-t;
a[num].r=x+t;
}
}
if(num==0){
cout<<0<<"\n";
continue;
}
sort(a+1,a+1+num,cmp);
int cnt=0,flag=0;
double pre=0;
for(int i=1;i<=num;i++){
if(pre>=w) break;
int t=i,ma=a[i].r,ans=i;
while(a[t].l<=pre&&t<=num){
if(ma<a[t].r){
ma=a[t].r;
ans=t;
}
t++;
}
if(a[ans].l<=pre){
cnt++;
i=ans;
pre=a[i].r;
}
else{
cout<<0<<"\n";
flag=1;
break;
}
}
if(!flag) cout<<cnt<<"\n";
}
return 0;
}
// 2147483647
1568

被折叠的 条评论
为什么被折叠?



