题目链接https://vjudge.net/problem/UVA-10382;
题目大意:有一块草坪,长为l,宽度为w.在其中心线的不同位置处装有n个点状喷水装置,每个喷水装置i,都可以把以他为中心半径为r的区域湿润,给你一些喷水装置,请选择尽量少的喷水装置,把整个草坪湿润。
思路:每个喷水装置就是一个圆,由于必须完全覆盖草坪,所以对于每个喷水装置只需要关注圆与草坪边缘交点,就可以了,所以对于每个喷水装置,转化为每个一个矩形,如图:
所以,可以把每个喷水装置装化为,一个矩形,求出矩形的左右坐标 l r,然后就可以转化为,几个区间求覆盖问题;具体如下:对所有区间的 l 进行排序,维护两个值 left right 刚开始记录为0;在所有左边界小于left的区间找到最大的r,更新right为r,然后把left更新为r;不断更新right和left当right大于总长度时就可以跳出,输出答案了,代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,l,w;
struct node
{
double left,right;
}wt[10010];
bool cmp(node a,node b)
{
return a.left<b.left;
}
int main()
{
while(~scanf("%d%d%d",&n,&l,&w))
{
double p,r;
int cnt=0;
for(int i=1;i<=n;i++)
{
scanf("%lf%lf",&p,&r);
if(r<=w/2.0)
continue;
double x1=sqrt(r*r-w*w/4.0);
wt[cnt].left=p-x1;
wt[cnt].right=p+x1;
cnt++;
}
sort(wt,wt+cnt,cmp);
double left=0,right=0;
int ans=0,flag=0;
if(wt[0].left<=0)
{
int i=0,j;
while(i<cnt)
{
j=i;
while(j<cnt&&left>=wt[j].left)
{
if(wt[j].right>right)
right=wt[j].right;
j++;
}
if(j==i)
break;
ans++;
left=right;
i=j;
if(left>=l)
{
flag=1;
break;
}
}
}
if(flag)
printf("%d\n",ans);
else
cout<<"-1"<<endl;
}
return 0;
}