bzoj1043: [HAOI2008]下落的圆盘

来源:互联网 发布:微信公众号排版 知乎 编辑:程序博客网 时间:2024/04/26 14:06

题目链接
有n个圆盘从天而降,后面落下的可以盖住前面的。求最后形成的封闭区域的周长。
直接模拟,求出当前圆盘与之前的所有的圆盘的交点,用极角表示,模拟结束后求出每个圆盘未被覆盖的角度即可。

#include <cmath>#include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int N = 1010;const double pi = acos(-1.0), eps = 1e-10;inline int cmp(const double &a) {    if (fabs(a) < eps) return 0;    return a > 0 ? 1 : -1;}#define pf(x) ((x)*(x))struct point {    double x, y;    point() {}    point(double __x, double __y): x(__x), y(__y) {}    inline void init() {        scanf("%lf%lf", &x, &y);    }    inline double norm() {        return sqrt(pf(x) + pf(y));    }    inline point operator - (const point &rhs) const {        return point(x - rhs.x, y - rhs.y);    }};struct node {    double rad;    bool flag;    node(double __rad, double __flag): rad(__rad), flag(__flag) {}    inline bool operator < (const node &rhs) const {//      if (rad == rhs.rad) return flag;        return rad < rhs.rad;    }};struct circle {    double r;    point o;    vector<node> ls;    circle() {ls.clear();}    inline void init() {        scanf("%lf", &r); o.init();    }}lib[N];int n;bool isCover[N];inline bool cover(circle up, circle &down) {    double d = (up.o - down.o).norm(), r1 = up.r, r2 = down.r;    if (cmp(d - r1 - r2) >= 0) return false;    if (cmp(r2 - r1 - d) >= 0) return false;    if (cmp(r1 - r2 - d) >= 0) return true;    point diff = up.o - down.o;//    double delta = acos((pf(d)+pf(r2)-pf(r1)) / 2 / d / r2), alpha = atan2(diff.y, diff.x);    double x1 = alpha - delta, x2 = alpha + delta;    if (x2 > pi) {        down.ls.push_back(node(x1, 1));        down.ls.push_back(node(pi, 0));        down.ls.push_back(node(-pi, 1));        down.ls.push_back(node(x2 - 2*pi, 0));    } else if (x1 < -pi) {        down.ls.push_back(node(x1 + 2*pi, 1));        down.ls.push_back(node(pi, 0));        down.ls.push_back(node(-pi, 1));        down.ls.push_back(node(x2, 0));    } else {        down.ls.push_back(node(x1, 1));        down.ls.push_back(node(x2, 0));    } //cout << down.ls.size() << endl;    return false;}inline double calc() {    double rst = 0;//  cout << lib[4].ls.size() << endl;    for (int i = 1; i <= n; i++) if (! isCover[i]) {        circle &o = lib[i];//      #define o lib[i]        if (! o.ls.size()) {            rst += 2*pi*o.r; continue;        }        sort(o.ls.begin(), o.ls.end());        int cnt = 0; double lst = -pi, sum = 0;        for (int j = 0; j < o.ls.size(); j++) {            double alpha = o.ls[j].rad, f = o.ls[j].flag;            if (! cnt) sum += alpha - lst;            if (f) cnt++; else cnt--;            if (! cnt) lst = alpha;        } sum += pi - lst;        rst += sum*o.r;//      #undef o    } return rst;}int main() {    scanf("%d", &n);    for (int i = 1; i <= n; i++) {        lib[i].init();        for (int j = 1; j < i; j++) if (! isCover[j])                isCover[j] = cover(lib[i], lib[j]);    } printf("%.3lf\n", calc());    return 0;}
0 0
原创粉丝点击