Source: UVa 10382
长 L 米,宽 W 米的草坪里装有 n 个浇灌喷头。每个喷头都装在草坪中心线上(离两边各 W /2米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。
请问:如果要同时浇灌整块草坪,最少需要打开多少个喷头
输入格式
输入包含若干组测试数据。
第一行一个整数 T 表示数据组数;
每组数据的第一行是整数 n、L 和 W;
接下来的 n 行,每行包含两个整数,给出一个喷头的位置和浇灌半径(上面的示意图是样例输入第一组数据所描述的情况)。
输出格式
对每组测试数据输出一个数字,表示要浇灌整块草坪所需喷头数目的最小值。如果所有喷头都打开也不能浇灌整块草坪,则输出 −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
算出每一个喷头的范围,然后按左端点排序,每一次找到一个区间最长满足且左端点落在并区间之间的区间人,如果无法区间完全覆盖直接-1
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 15010;
class Node {
public:double l;//区间左边
double r;//区间右边
};
bool cmp(Node a, Node b) {
if (a.l != b.l) {
return a.l < b.l;
}
else if(a.r!=b.r){
return a.r > b.r;
};
};
int main() {
int t, n,site,flag;double length, width,len=0,radius=0;
Node* s = new Node[N];
cin >> t;
for (int i = 1; i <= t; i++) {
cin >> n >> length >> width;
double mid = width / 2;
flag = 1;
for (int j = 1; j <= n; j++) {
cin >> site>> radius;
if (radius >= mid) {
len = sqrt(radius * radius - mid * mid);
s[flag].l = site - len;
s[flag].r = site + len;
flag++;
}
};
sort(s + 1, s + 1 + flag, cmp);//从小排序
double left = 0;
int res = 0,f=1;
while (left < length) {
double last = left;//用于保存开始的左端点
res++;
for (int i = 1; i <= flag; i++) {//找到一个最大值
if (s[i].l <= last && s[i].r >= left) {
left = s[i].r;
};
};
if (left == last && left < length) {
cout << -1 << endl;;
f = 0;
break;
};
};
if (f) {
cout << res << endl;
};
};
return 0;
};