uvalive 2572

来源:互联网 发布:数据透视图 总数 编辑:程序博客网 时间:2024/06/06 00:43

题意:把n个圆盘依次放到桌面上,按放的顺序给出每个圆盘的坐标和半径,问最后多少个圆盘可见。
题解:如果把所有圆盘放好,基本上看到的都是完整的圆盘或者一些圆弧,那么把每一个圆盘和其他圆盘的交点求出来,每两个相邻的交点之间的圆弧也就可以得到,然后把这个圆弧的中点P往内外各移动一个很小的距离,得到P’和P”,把包含这两个点的最顶部的圆盘视为可见。注意很小的距离的取值。

#include <cstdio>#include <vector>#include <cstring>#include <cmath>#include <algorithm>using namespace std;const double eps = 5e-13;const double PI = acos(-1);struct Point {    double x, y;    Point(double x = 0, double y = 0): x(x), y(y) {}};struct Circle {    Point c;    double r;    Circle() {}    Circle(Point c, double r = 0): c(c), r(r) {}    Point point(double a) {        return Point(c.x + cos(a) * r, c.y + sin(a) * c.y);    }};int n, flag[105];Circle cir[105];//重载运算符Point operator + (Point A, Point B) {    return Point(A.x + B.x, A.y + B.y);}Point operator - (Point A, Point B) {    return Point(A.x - B.x, A.y - B.y);}Point operator * (Point A, double p) {    return Point(A.x * p, A.y * p);}Point operator / (Point A, double p) {    return Point(A.x / p, A.y / p);}//计算点积的正负  负值夹角为钝角int dcmp(double x) {    if (fabs(x) < eps)        return 0;    return x < 0 ? -1 : 1;}bool operator == (const Point& a, const Point& b) {    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;}bool operator < (const Point& a, const Point& b) {    return a.x < b.x || (a.x == b.x && a.y < b.y);}//计算点积 正负和夹角有关 |a||b|cosCdouble Dot(Point A, Point B) {    return A.x * B.x + A.y * B.y;}//计算叉积,也就是数量积 向量A和B组成的三角形的有向面积的两倍//叉积等于0 三角形成为线段double Cross(Point A, Point B) {    return A.x * B.y - A.y * B.x;}//计算向量长度double Length(Point A) {    return sqrt(Dot(A, A));}//向量A旋转rad弧度,rad负值为顺时针旋转Point Rotate(Point A, double rad) {    return Point(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));}void GetCircleIntersection(Circle a, Circle b, vector<double>& v) {    if (dcmp(Length(a.c - b.c)) == 0)        return;    if (dcmp(Length(a.c - b.c) - a.r - b.r) > 0)        return;    if (dcmp(fabs(a.r - b.r) - Length(a.c - b.c)) > 0)        return;    double ang = atan2(b.c.y - a.c.y, b.c.x - a.c.x);    double ang1 = acos((a.r * a.r + Length(a.c - b.c) * Length(a.c - b.c) - b.r * b.r) / (2.0 * a.r * Length(a.c - b.c)));    v.push_back(ang - ang1);    v.push_back(ang + ang1);}int topmost(Point p) {    for (int i = n - 1; i >= 0; i--)        if (Length(cir[i].c - p) < cir[i].r)            return i;    return -1;}int main() {    while (scanf("%d", &n) == 1 && n) {        memset(flag, 0, sizeof(flag));        int cnt = 0;        for (int i = 0; i < n; i++)            scanf("%lf%lf%lf", &cir[i].c.x, &cir[i].c.y, &cir[i].r);        for (int i = 0; i < n; i++) {            vector<double> v;            v.push_back(0);            v.push_back(PI * 2);            for (int j = 0; j < n; j++)                GetCircleIntersection(cir[i], cir[j], v);            sort(v.begin(), v.end());            for (int j = 0; j < v.size(); j++) {                double mid = (v[j] + v[j + 1]) / 2.0;                double r1 = cir[i].r + eps;                     int t = topmost(Point(cir[i].c.x + cos(mid) * r1, cir[i].c.y + sin(mid) * r1));                if (t >= 0)                    flag[t] = 1;                double r2 = cir[i].r - eps;                t = topmost(Point(cir[i].c.x + cos(mid) * r2, cir[i].c.y + sin(mid) * r2));                if (t >= 0)                    flag[t] = 1;            }        }        int res = 0;        for (int i = 0; i < n; i++)            if (flag[i])                res++;        printf("%d\n", res);    }    return 0;}
0 0
原创粉丝点击