uva 10969

题意:平面上依次放置n个圆,后放的覆盖先放的,按顺序给出每个圆的半径和圆心坐标,问最后图形的可见圆弧长之和。

题解:因为是后放的覆盖先放的,所以逆序枚举,每个圆只考虑之前放过的圆和自己的交点,把所有交点排序后可以得到每两个相邻的交点之间的圆弧,找到圆弧中点,如果这个点在之前放过的圆内,说明这个圆弧不能要,否则加到答案里。注意弧度要规范到0~2π。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
const double PI = acos(-1);
const double eps = 1e-11;
struct Point {
    double x, y;
    Point(double x = 0, double y = 0): x(x), y(y) {}
};
typedef Point Vector;

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);
    }
};

double dcmp(double x) {
    if (fabs(x) < eps)
        return 0;
    return x < 0 ? -1 : 1;
}
Vector operator + (const Point& A, const Point& B) {
    return Vector(A.x + B.x, A.y + B.y);
}
Vector operator - (const Point& A, const Point& B) {
    return Vector(A.x - B.x, A.y - B.y);
}
Vector operator * (const Point& A, double a) {
    return Vector(A.x * a, A.y * a);
}
Vector operator / (const Point& A, double a) {
    return Vector(A.x / a, A.y / a);
}
double Cross(const Vector& A, const Vector& B) {
    return A.x * B.y - A.y * B.x;
}
double Dot(const Vector& A, const Vector& B) {
    return A.x * B.x + A.y * B.y;
}
double Length(const Vector& A) {
    return sqrt(Dot(A, A));
}
double Angle(Vector A, Vector B) {
    return acos(Dot(A, B) / Length(A) / Length(B));
}
bool operator < (const Point& A, const Point& B) {
    return A.x < B.x || (A.x == B.x && A.y < B.y);
}
bool operator == (const Point& A, const Point& B) {
    return A.x == B.x && A.y == B.y;
}
Point Rotate(Point A, double rad) {
    return Point(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));
}
double torad(double deg) {
    return deg / 180.0 * PI;
}
double normal(double rad) {
    return rad - 2.0 * M_PI * floor(rad / 2.0 / M_PI);
}
void GetCircleIntersection(Circle a, Circle b, vector<double>& v) {
    if (dcmp(Length(a.c - b.c)) == 0)
        return;
    if (dcmp(a.r + b.r - Length(a.c - b.c)) < 0)
        return;
    if (dcmp(fabs(a.r - b.r) - Length(a.c - b.c)) > 0)
        return;
    double rad = atan2(b.c.y - a.c.y, b.c.x - a.c.x);
    double rad1 = 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(normal(rad - rad1));
    v.push_back(normal(rad + rad1));
}

const int N = 105;
int n;
Circle cir[N];

bool judge(int cur, Point p) {
    for (int i = n - 1; i > cur; i--)
        if (dcmp(Length(cir[i].c - p) - cir[i].r) <= 0)
            return false;
    return true;
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        scanf("%d", &n);
        for (int i = 0; i < n; i++)
            scanf("%lf%lf%lf", &cir[i].r, &cir[i].c.x, &cir[i].c.y);
        double res = 0;
        for (int i = n - 1; i >= 0; i--) {
            vector<double> v;
            v.push_back(0);
            v.push_back(PI * 2);
            for (int j = n - 1; j > i; j--)
                GetCircleIntersection(cir[i], cir[j], v);
            sort(v.begin(), v.end());
            double temp = 0;
            for (int j = 0; j < v.size() - 1; j++) {
                double mid = (v[j] + v[j + 1]) / 2.0;
                if (judge(i, Point(cir[i].c.x + cos(mid) * cir[i].r, cir[i].c.y + sin(mid) * cir[i].r)))
                    temp += v[j + 1] - v[j];
            }
            res += temp * cir[i].r;
        }
        printf("%.3lf\n", res);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-05 08:42:52

uva 10969的相关文章

UVa 10969 (圆与圆之间的覆盖问题) Sweet Dream

题意: 有n个按先后顺序放置的不同大小不同位置的圆,求所有可见圆弧的长度. 分析: 这道题应该是大白书上例题 LA 2572 (求可见圆盘的数量) Kanazawa 的加强版,整体框架都差不多. 对于每个圆求出与其他圆相交的交点所对应的幅角(转化到[0, 2π]中),排个序,然后枚举每段弧的终点,如果不被后面放置的圆所覆盖则可见. 注意: 原本以为WA是精度问题,后来调大调小都一直WA,这里精度eps从1e-11到1e-13都没问题. 但是在判断弧的终点是否被圆所覆盖的时候要加上等号.也就是第6

UVA - 10969 Sweet Dream

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34782 Problem 从楼上往下丢N个圆,告诉圆的半径和落点,求最终图形的可见弧长之和.N<=100 Solution 实际上可以转换为圆求交.逆着来,i : n->1,j : i+1->n,求出 i 与 j 的交点(同时考虑无交点和完全覆盖的情况),把交点按极角排序,然后就变成了区间覆盖问题了,给若干个区间,统计未被覆盖的长度(在此题实际上是角度)之和,然后就知

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d

UVA 10341 Solve It

Problem F Solve It Input: standard input Output: standard output Time Limit: 1 second Memory Limit: 32 MB Solve the equation: p*e-x + q*sin(x) + r*cos(x) + s*tan(x) + t*x2 + u = 0 where 0 <= x <= 1. Input Input consists of multiple test cases and te

UVA 11014 - Make a Crystal(容斥原理)

UVA 11014 - Make a Crystal 题目链接 题意:给定一个NxNxN的正方体,求出最多能选几个整数点.使得随意两点PQ不会使PQO共线. 思路:利用容斥原理,设f(k)为点(x, y, z)三点都为k的倍数的点的个数(要扣掉一个原点O).那么全部点就是f(1),之后要去除掉共线的,就是扣掉f(2), f(3), f(5)..f(n).n为素数.由于这些素数中包括了合数的情况,而且这些点必定与f(1)除去这些点以外的点共线,所以扣掉.可是扣掉后会扣掉一些反复的.比方f(6)在f

[UVa] Palindromes(401)

UVA - 401 Palindromes Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description A regular palindrome is a string of numbers or letters that is the same forward as backward. For example, the string "ABCDED

uva 401.Palindromes

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=342 题目意思:给出一段字符串(大写字母+数字组成).判断是否为回文串 or 镜像串 or 回文镜像串 or 什么都不是.每个字母的镜像表格如下 Character Reverse Character Reverse Character Reverse A A M M Y Y B

[2016-02-19][UVA][129][Krypton Factor]

UVA - 129 Krypton Factor Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu Submit Status Description You have been employed by the organisers of a Super Krypton Factor Contest in which contestants have very high mental and physica

[2016-02-03][UVA][514][Rails]

时间:2016-02-03 22:24:52 星期三 题目编号:UVA 514 题目大意:给定若干的火车(编号1-n),按1-n的顺序进入车站, 给出火车出站的顺序,问是否有可能存在 分析:    FIFO,用栈模拟一遍即可, 方法:    根据输入的顺序,从1-n开始,当前操作的为i 如果i是当前对应的编号,那么直接跳过(进入B) 如果不是,根据当前需求的编号,小于i,就从栈顶弹出一个元素, 看这个元素是否是需求的,是则继续.否则NO 1 2 3 4 5 6 7 8 9 10 11 12 13