【问题】
长 L 米,宽 W 米的草坪里装有 n 个浇灌喷头。每个喷头都装在草坪中心线上(离两边各 w 2 \frac{w}{2} 2w 米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。
请问:如果要同时浇灌整块草坪,最少需要打开多少个喷头?【输入】
输入包含若干组测试数据。
第一行一个整数 T 表示数据组数;
每组数据的第一行是整数 n、L 和 W;
接下来的 n 行,每行包含两个整数,给出一个喷头的位置和浇灌半径(上面的示意图是样例输入第一组数据所描述的情况)。【输出】
对每组测试数据输出一个数字,表示要浇灌整块草坪所需喷头数目的最小值。如果所有喷头都打开也不能浇灌整块草坪,则输出 -1
【思路】
首先计算一下每个喷水装置的有效覆盖范围(因为是圆形区域,如下图红线区域为有效区域),存入数组中,按照区域首排序。
然后在进行操作,典型的区间覆盖问题,具体看代码。
【源代码】
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 100000+5;
struct Node
{
double pos;
double num;
bool operator < (const Node &b)const
{
return pos< b.pos;
}
} node[N];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,l,w;
scanf("%d%d%d",&n,&l,&w);
int cnt=0;
for(int i=1; i<=n; i++)
{
int pos,r;
scanf("%d%d",&pos,&r);
if(r>w/2)
{
node[++cnt].pos=pos-sqrt(r*r-(w/2.0)*(w/2.0));
node[cnt].num=pos+sqrt(r*r-(w/2.0)*(w/2.0));
}
}
sort(node+1,node+1+cnt);
double len=0;
int res=0;
bool flag=true;
int i=1;
while(len<l)
{
res++;
double pos=len;
while(node[i].pos<=pos&&i<=cnt)
{
if(len<node[i].num)
len=node[i].num;
i++;
}
if(len==pos&&pos<l)
{
printf("-1\n");
flag=false;
break;
}
}
if(flag)
printf("%d\n",res);
}
return 0;
}