CF82E-Corridor

这屑题可能是计算几何题中的难得的良心题了。。。这题其实就是灯照进去每个窗的面积总和减去灯光相交、重叠部分的面积。

  1. 灯照进去每个窗的面积总和

    我们很容易发现这题灯照进去每个窗的面积其实就是一个梯形的面积,这个梯形的高就是

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108

    2. 重叠面积

    重叠部分一般为三角形,但如果有光束的交点的纵坐标在```-h~h```之外时,是梯形。计算面积是用之前求出的函数解析式求出两条边缘光束的交点、边缘光束与x轴的交点,然后计算面积即可。

    最后容斥原理计算一下面积就行了。

    上代码:

    ```cpp
    #include <bits/stdc++.h>
    #define eps 1e-8
    #define SGN(x) ((x) > eps ? 1 : ((x) > -eps ? 0 : -1))
    using namespace std;

    struct point {
    double x, y;
    point() {}
    point(double _x, double _y) : x(_x), y(_y) {}
    point operator-(const point p1) { return point(x - p1.x, y - p1.y); }
    };

    double cross(const point &a, const point &b, const point &c) {
    return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
    }

    double cross(const point &a, const point &b) { return a.x * b.y - a.y * b.x; }

    double dot(const point &a, const point &b) { return a.x * b.x + a.y * b.y; }

    point its(const point &a, const point &b, const point &c, const point &d) {
    point ret = a;
    double t = ((c.x - a.x) * (d.y - c.y) - (c.y - a.y) * (d.x - c.x)) /
    ((b.x - a.x) * (d.y - c.y) - (b.y - a.y) * (d.x - c.x));
    ret.x += (b.x - a.x) * t;
    ret.y += (b.y - a.y) * t;
    return ret;
    }

    int n;
    point p[1010][4];

    pair<double, int> e[5000];
    int cnt;

    inline void insert(point &s, point &t, point X, int inc) {
    double ratio =
    SGN(t.x - s.x) ? (X.x - s.x) / (t.x - s.x) : (X.y - s.y) / (t.y - s.y);
    e[cnt++] = make_pair(ratio, inc);
    }

    double h, f;

    int main() {
    scanf("%d%lf%lf", &n, &h, &f);
    point p1(0, -f), p2(0, f);
    for (int i = 0; i < n; ++i) {
    double l, r;
    scanf("%lf%lf", &l, &r);
    p[i * 2][0] = point(l, -h);
    p[i * 2][1] = point(r, -h);
    p[i * 2][2] = its(p1, point(r, -h), point(0, h), point(100, h));
    p[i * 2][3] = its(p1, point(l, -h), point(0, h), point(100, h));
    p[i * 2 + 1][0] = point(r, h);
    p[i * 2 + 1][1] = point(l, h);
    p[i * 2 + 1][2] = its(p2, point(l, h), point(0, -h), point(100, -h));
    p[i * 2 + 1][3] = its(p2, point(r, h), point(0, -h), point(100, -h));
    }
    n *= 2;
    double ans = 0.0;
    int cp0, cp1, cp2;
    for (int i = 0; i < n; i++) {
    for (int k = 0; k < 4; k++) {
    point &s = p[i][k], &t = p[i][k == 3 ? 0 : k + 1];
    cnt = 0;
    e[cnt++] = make_pair(0.0, 1);
    e[cnt++] = make_pair(1.0, -1);
    for (int j = 0; j < n; j++)
    if (i != j) {
    for (int l = 0; l < 4; l++) {
    cp0 = SGN(cross(s, t, p[j][l == 0 ? 3 : l - 1]));
    cp1 = SGN(cross(s, t, p[j][l]));
    cp2 = SGN(cross(s, t, p[j][l == 3 ? 0 : l + 1]));
    if (cp1 * cp2 < 0)
    insert(s, t, its(s, t, p[j][l], p[j][l == 3 ? 0 : l + 1]), cp2);
    else if (!cp1 && cp0 * cp2 < 0)
    insert(s, t, p[j][l], cp2);
    else if (!cp1 && !cp2 && j > i &&
    dot(t - s, p[j][l == 3 ? 0 : l + 1] - p[j][l]) > -eps) {
    insert(s, t, p[j][l], -1);
    insert(s, t, p[j][l == 3 ? 0 : l + 1], 1);
    }
    }
    }
    sort(e, e + cnt);
    int acc = 0;
    double total = 0.0, last;
    for (int j = 0; j < cnt; j++) {
    acc += e[j].second;
    if (acc == 0 && e[j].second < 0)
    total += e[j].first - last;
    last = e[j].first;
    }
    ans += cross(s, t) * total;
    }
    }
    printf("%.10lf\n", ans * 0.5);
    }


   转载规则


《CF82E-Corridor》 VinovnyyPoterpevshiy 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
CF87E-Mogohu-Rea-Idol CF87E-Mogohu-Rea-Idol
题解是真的简单。。。就是对三个凸包求$Minkowski sum$,然后判断点是否在凸多边形内即可。。。 这题竟然还保证一个多边形内三点不共线。。。于是判断一个点是否在一个多边形边上变得更简单。。。一开始竟然没有看到这个条件,在那里进行检查
2019-09-22
下一篇 
CF78E-Evacuation CF78E-Evacuation
分析数据 我们可以将一个科学家可以在t分钟之内从(x0,y0)移动到(x1,y1)作为(x0,y0)在t时刻联通。 建图 现在我们有一个网格图了,我们可以再将其转化一下。我们构造有一个源点,一个汇点,中间有两个层,每层$n^2
2019-09-22
  目录