题目:有一个矩形,矩形的中心线上有n(10000)个不同的圆,现用最小数量的圆覆盖整个矩形区域。
思路:首先将圆的覆盖区域转化为一个矩形,矩形的左边界和右边界可求。然后贪心的从左边开始选取,此策略可保证需要的圆数量最小。
ps:
(1)浮点数比较需要引入eps比较
(2)int型的数相乘可能会导致爆int,需要使用double
代码:
#include <cstdio>
#include <algorithm>
#include <cmath>
#define db double
using namespace std;
const int maxn = 10000 + 100;
const db eps = 1e-11;
struct Node {
db l, r;
bool operator < (const Node &a) const {
return l < a.l || (l == a.l && r < a.r);
}
}A[maxn];
db l, w;
int n;
int main(){
freopen("a.in", "r", stdin);
freopen("a.out", "w", stdout);
while (scanf("%d %lf %lf", &n, &l, &w) == 3) {
int cnt = 0;
for (int i = 0; i < n; i ++) {
db pos, r; scanf("%lf %lf", &pos, &r);
if (r <= w / 2) continue;
db tmp = sqrt(r*r - w/2*w/2);
db L = pos - tmp, R = pos + tmp;
if (L >= l || R <= 0) continue;
if (L < 0) L = 0;
A[cnt++] = (Node){L, R};
}
sort(A, A + cnt);
db st = 0, ed = 0;
int ans = 0;
for (int i = 0; i < cnt; ) {
st = ed;
if (A[i].l > st + eps) {ans = -1; break;}
ans ++;
while (i < cnt && A[i].l <= st) {
if (A[i].r > ed + eps) ed = A[i].r;
i ++;
}
if (ed >= l) break;
}
if (ed + eps < l) ans = -1;
printf("%d\n", ans);
}
return 0;
}