uva10382(贪心)

题目:有一个矩形,矩形的中心线上有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;
}

猜你喜欢

转载自blog.csdn.net/m0_37577390/article/details/81837658