1424 喷水装置
所关于贪心的问题,大部分都是这些类似于区间段重合问题
也就是给定n个喷水的装置,再给定他们的喷水范围,问要想让所有的草坪都能被喷到水,最少需要多少水龙头?
一个圆看上去可以利用的地方很多,实际上就只有中间的部分可以利用
所以我们把圆转化成线段
a[cnt].s =p -sqrt((rr)-(w/2.0)(w/2.0));
a[cnt].e =p +sqrt((rr)-(w/2.0)(w/2.0));
其中结构题记录转成线段后的起点和终点
转化成线段就可以把题目转化成刚才做过的那道题了
这个题的难点就在于将圆转化成线段
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
using namespace std;
int t;
int n,qi,zhong;
int p,r;
int tot;
struct node
{
double x,y;
}a[20005];
bool cmp(node a,node b)
{
return a.x<b.x;
}
void read()
{
cin>>n>>qi>>zhong;
tot=0;
for(int i=1;i<=n;i++)
{
cin>>p>>r;
if(r<=zhong/2) continue;//直径不够,不考虑
tot++;
a[tot].x=p-sqrt((r*r)-(zhong*zhong/4.0));
a[tot].y=p+sqrt((r*r)-(zhong*zhong/4.0));//转化成线段
}
}
void sol()
{
int ans=0;
bool flag=1;
int i=1;
double t=0;
while(t<qi)
{
ans++;//计算答案
double x=t;
for(;a[i].x<=x&&i<=tot;i++)
{
if(t<a[i].y) t=a[i].y;//寻找能够覆盖l点的最大右端点
}
if(t==x&&x<qi)//无解
{
flag=0;
cout<<-1<<endl;
break;
}
}
if(flag)
cout<<ans<<endl;
}
int main()
{
cin>>t;
while(t--)
{
read();
sort(a+1,a+1+tot,cmp);
sol();
}
return 0;
}