题目描述
长 L L L 米,宽 W W W 米的草坪里装有 n n n 个浇灌喷头。每个喷头都装在草坪中心线上(离两边各 w 2 w \over 2 2w 米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。
请问:如果要同时浇灌整块草坪,最少需要打开多少个喷头?
输入格式
输入包含若干组测试数据。
第一行一个整数 T T T 表示数据组数;
每组数据的第一行是整数 n n n、 L L L 和 W W W;
接下来的 n n n 行,每行包含两个整数,给出一个喷头的位置和浇灌半径(上面的示意图是样例输入第一组数据所描述的情况)。
输出格式
对每组测试数据输出一个数字,表示要浇灌整块草坪所需喷头数目的最小值。如果所有喷头都打开也不能浇灌整块草坪,则输出 − 1 -1 −1。
样例输入
3
8 20 2
5 3
4 1
1 2
7 2
10 2
13 3
16 2
19 4
3 10 1
3 5
9 3
6 1
3 10 1
5 3
1 1
9 1
样例输出
6
2
-1
思路
如果一个圆的半径小于等于
w
2
w \over 2
2w 那么这个喷头肯定不选。
再在可能选的喷头中算出每个喷头覆盖范围的左端点和右端点。
现在
w
2
w \over 2
2w和
r
r
r 已知,只需用勾股定理算出x即可。
然后按左端点排序,找能覆盖已覆盖范围的右端点的喷头,选其中右端点最大的一个。
代码
#include <bits/stdc++.h>
using namespace std;
struct node
{
double x, y;
}a[21000];
bool cmp(node x, node y)
{
return x.x < y.x;
}
int n, l, w, x, r, tmp;
int main()
{
int T;
cin >> T;
while(T--)
{
cin >> n >> l >> w;
tmp = 0;
for (int i = 1; i <= n; i++)
{
cin >> x >> r;
if (r <= w / 2) continue;
tmp++;
a[tmp].x = x - sqrt(r * r - w * w / 4.0);
a[tmp].y = x + sqrt(r * r - w * w / 4.0);
}
sort (a + 1, a + tmp + 1, cmp);
double tp = 0;
int ans = 0, f = 1;
while (tp < l)
{
ans++;
double t = tp;
for (int i = 1; a[i].x <= t && i <= tmp; i++)
{
if (tp < a[i].y) tp = a[i].y;
}
if (tp == t && t <= l)
{
cout << -1 << endl;
f = 0;
break;
}
}
if (f == 1) printf("%d\n",ans);
}
return 0;
}