[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