兔兔 的 题解 —— 喷水装置

喷水装置


题目描述

在一个长 L L 米,宽 W W 米的草坪里装有 N N 个浇灌喷头。
每一个喷头都装在草坪中心线上 (离两边各 W 2 \frac W 2 米)
咱们知道每一个喷头的位置 C C (离草坪中心线左端的距离),以及它能覆盖到的浇灌范围 R R
请问:最少须要打开多少个喷头才能浇灌整块草坪?喷水装置 —— 图html

输入格式

输入包含若干组测试数据。
第一行一个整数 T T ,表示数据的组数;
每组数据的第一行是整数 N N L L W W
接下来的 行,每行包含两个整数,给出一个喷头的位置和浇灌半径 (上面的示意图是样例输入第一组数据所描述的状况)。node

输出格式

对每组测试数据输出一个数字,表示为浇灌整块草坪所需喷头数目的最小值。
若是全部喷头都打开也不能浇灌整块草坪,则输出 1 -1 web

样例

样例输入

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 1app

样例输出

6
2
-1svg

数据范围

对于 100 100% 的数据, N < = 15000 N <= 15000 测试

提示

贪心spa


分析

对于任意一个喷水装置,它能喷洒到的区域是一个已知半径的圆形。
可是喷洒到草坪上的区域,则是近似一个矩形的。
这个矩形就是圆形与草坪的四个交点所围成的矩形。 (在这里兔兔不方便画图,就须要读者本身在草稿本上画图了)
咱们能够求出每一个喷水装置在草坪上喷洒的区域 (以前所说的矩形) 的 左端点右端点
而后在全部左端点小于上一个区间右端点的区域中选择右端点最大的一个喷水装置。
剩下的分析,兔兔就附在代码上了哦~code


代码

下面是正解代码 (请读者不要抄袭哦~):xml

#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;

const int MAXN = 15005;
int T;
int N, L, W;
struct node {
	double l, r;
}P[MAXN];
int cnt;

int main()
{
	while (scanf("%d", &T) != EOF)
	{
		for (int i = 1; i <= T; i++)
		{
			scanf("%d %d %d", &N, &L, &W);
			cnt = 0;
			for (int j = 1; j <= N; j++)
			{
				double C, R;
				scanf("%lf %lf", &C, &R);
				double x = 1.0 * sqrt((1.0 * R * R) - ((W / 2.0) * (W / 2.0))); // 勾股定理, 为何须要这样求呢? 就留给读者本身思考了哦~ 
				if (R * 2 <= W) continue;
				++cnt;
				P[cnt].l = max((double)0, C - x); // 若是它的左端点超出了左边界0 , 则把它的左端点设置为左边界 
				P[cnt].r = min((double)L, C + x); // 若是它的右端点超出了右边界L , 则把它的右端点设置为右边界 
			}
			int ans = 0;
			double maxr = 0.0;
			bool check = 0;
			while (maxr < L)
			{
				double nowl = maxr;
				for (int j = 1; j <= cnt; j++)
					if (P[j].l <= nowl && P[j].r > maxr) maxr = P[j].r;
				if (maxr == nowl)
				{
					check = 1;
					break;
				}
				++ans;
			}
			if (check) printf("-1");
			else printf("%d", ans);
			printf("\n");
		}
	}
	return 0;
}

若是须要兔兔改进的地方,能够在评论区留言,也能够私信兔兔哦~htm