其他分享
首页 > 其他分享> > [Loj#10002]喷水装置

[Loj#10002]喷水装置

作者:互联网

discription:
长\(L\)米,宽\(W\)米的草坪里装有\(n\)个浇灌喷头。每个喷头都装在草坪中心线上(离两边各\(\frac{W}{2}\)米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。

请问:如果要同时浇灌整块草坪,最少需要打开多少个喷头?
solution:
先预处理圆覆盖矩形块的左右边界(勾股定理);
因为要尽量少选择区间以覆盖\(L\), 对区间按右边界降序排列, 每次从左至右选择能覆盖当前右边界的区间, 选不出则失败;
可以对选过的区间打vis, 减少遍历.
code:

#include<cstdio>
#include<cmath>
#include<algorithm>
const int maxn(15005);
struct range {
	range() :vis(0), l(0), r(0) {}
	double l, r;
	bool vis;
	bool operator < (const range& a) {
		return this->r > a.r;
	}
};
int main() {
	int T; scanf("%d", &T);
	while (T--) {
		range a[maxn];
		int N; double L, W; scanf("%d%lf%lf", &N, &L, &W);
		int size(0);
		while(N--) {
			double pos, R; scanf("%lf%lf", &pos, &R);
			if (2 * R > W) {
				a[size].l = pos - sqrt(R * R - 0.25 * W * W);
				a[size++].r = pos + sqrt(R * R - 0.25 * W * W);
			}
		}
		std::sort(a, a + size);
		if (a[0].r < L) { printf("-1\n"); continue; }
		double rt(0.0);
		int ans(0);
		for(;;) {
			if (rt >= L) { printf("%d\n", ans); break; }
			bool f = 1;
			for (int i = 0; !a[i].vis && i < size; ++i) {
				if (a[i].l <= rt) {
					++ans, f = 0, a[i].vis = 1, rt = a[i].r;
					break;
				}
			}
			if (f) { printf("-1\n"); break; }
		}
	}
}

标签:10002,vis,Loj,double,pos,int,range,喷水,size
来源: https://www.cnblogs.com/dwt2021/p/14415058.html