CIRU - The area of the union of circles

no tags 

You are given N circles and expected to calculate the area of the union of the circles !

Input

The first line is one integer n indicates the number of the circles. (1 <= n <= 1000)

Then follows n lines every line has three integers

Xi Yi Ri

indicates the coordinate of the center of the circle, and the radius. (|Xi|. |Yi|  <= 1000, Ri <= 1000)

Note that in this problem Ri may be 0 and it just means one point !

Output

The total area that these N circles with 3 digits after decimal point

Example

Input:
3
0 0 1
0 0 1
100 100 1 Output:
6.283
代码详解见 : http://www.cnblogs.com/oyking/p/3424999.html
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#define inf 0x3f3f3f3f
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
typedef long long ll;
using namespace std;
const int N = 1e5+;
const int M = ;
const double PI = acos(-1.0);
const double EPS = 1e-; inline int sgn(double x) {
return (x > EPS) - (x < -EPS);
} struct Point {
double x, y;
Point() {}
Point(double x, double y): x(x), y(y) {}
void read() {
scanf("%lf%lf", &x, &y);
}
double angle() {
return atan2(y, x);
}
Point operator + (const Point &rhs) const {
return Point(x + rhs.x, y + rhs.y);
}
Point operator - (const Point &rhs) const {
return Point(x - rhs.x, y - rhs.y);
}
Point operator * (double t) const {
return Point(x * t, y * t);
}
Point operator / (double t) const {
return Point(x / t, y / t);
}
double length() const {
return sqrt(x * x + y * y);
}
Point unit() const {
double l = length();
return Point(x / l, y / l);
}
}; double cross(const Point &a, const Point &b) {
return a.x * b.y - a.y * b.x;
} double dist(const Point &p1, const Point &p2) {
return (p1 - p2).length();
} Point rotate(const Point &p, double angle, const Point &o = Point(, )) {
Point t = p - o;
double x = t.x * cos(angle) - t.y * sin(angle);
double y = t.y * cos(angle) + t.x * sin(angle);
return Point(x, y) + o;
} struct Region {
double st, ed;
Region() {}
Region(double st, double ed): st(st), ed(ed) {}
bool operator < (const Region &rhs) const {
if(sgn(st - rhs.st)) return st < rhs.st;
return ed < rhs.ed;
}
}; struct Circle {
Point c;
double r;
vector<Region> reg;
Circle() {}
Circle(Point c, double r): c(c), r(r) {}
void read() {
c.read();
scanf("%lf", &r);
}
void add(const Region &r) {
reg.push_back(r);
}
bool contain(const Circle &cir) const {
return sgn(dist(cir.c, c) + cir.r - r) <= ;
}
bool intersect(const Circle &cir) const {
return sgn(dist(cir.c, c) - cir.r - r) < ;
}
}; double sqr(double x) {
return x * x;
} void intersection(const Circle &cir1, const Circle &cir2, Point &p1, Point &p2) {
double l = dist(cir1.c, cir2.c);
double d = (sqr(l) - sqr(cir2.r) + sqr(cir1.r)) / ( * l);
double d2 = sqrt(sqr(cir1.r) - sqr(d));
Point mid = cir1.c + (cir2.c - cir1.c).unit() * d;
Point v = rotate(cir2.c - cir1.c, PI / ).unit() * d2;
p1 = mid + v, p2 = mid - v;
} Point calc(const Circle &cir, double angle) {
Point p = Point(cir.c.x + cir.r, cir.c.y);
return rotate(p, angle, cir.c);
} const int MAXN = ; Circle cir[MAXN];
bool del[MAXN];
int n; double solve() {
double ans = ;
for(int i = ; i < n; ++i) {
for(int j = ; j < n; ++j) if(!del[j]) {
if(i == j) continue;
if(cir[j].contain(cir[i])) {
del[i] = true;
break;
}
}
}
for(int i = ; i < n; ++i) if(!del[i]) {
Circle &mc = cir[i];
Point p1, p2;
bool flag = false;
for(int j = ; j < n; ++j) if(!del[j]) {
if(i == j) continue;
if(!mc.intersect(cir[j])) continue;
flag = true;
intersection(mc, cir[j], p1, p2);
double rs = (p2 - mc.c).angle(), rt = (p1 - mc.c).angle();
if(sgn(rs) < ) rs += * PI;
if(sgn(rt) < ) rt += * PI;
if(sgn(rs - rt) > ) mc.add(Region(rs, PI * )), mc.add(Region(, rt));
else mc.add(Region(rs, rt));
}
if(!flag) {
ans += PI * sqr(mc.r);
continue;
}
sort(mc.reg.begin(), mc.reg.end());
int cnt = ;
for(int j = ; j < int(mc.reg.size()); ++j) {
if(sgn(mc.reg[cnt - ].ed - mc.reg[j].st) >= ) {
mc.reg[cnt - ].ed = max(mc.reg[cnt - ].ed, mc.reg[j].ed);
} else mc.reg[cnt++] = mc.reg[j];
}
mc.add(Region());
mc.reg[cnt] = mc.reg[];
for(int j = ; j < cnt; ++j) {
p1 = calc(mc, mc.reg[j].ed);
p2 = calc(mc, mc.reg[j + ].st);
ans += cross(p1, p2) / ;
double angle = mc.reg[j + ].st - mc.reg[j].ed;
if(sgn(angle) < ) angle += * PI;
ans += 0.5 * sqr(mc.r) * (angle - sin(angle));
}
}
return ans;
} int main() {
scanf("%d", &n);
for(int i = ; i < n; ++i) cir[i].read();
printf("%.3f\n", solve() + EPS);
}

SPOJ CIRU - The area of the union of circles (圆的面积并)的更多相关文章

  1. SPOJ CIRU The area of the union of circles

    You are given N circles and expected to calculate the area of the union of the circles ! Input The f ...

  2. SPOJ CIRU The area of the union of circles (计算几何)

    题意:求 m 个圆的并的面积. 析:就是一个板子题,还有要注意圆的半径为0的情况. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024 ...

  3. SPOJ CIRU The area of the union of circles ——Simpson积分

    [题目分析] 圆的面积并. 直接Simpson积分,(但是有计算几何的解法,留着flag). simpson积分,如果圆出现了不连续的情况,是很容易出事情的.(脑补一下) 但是没有什么办法,本来就是一 ...

  4. 【题解】CIRU - The area of the union of circles [SP8073] \ 圆的面积并 [Bzoj2178]

    [题解]CIRU - The area of the union of circles [SP8073] \ 圆的面积并 [Bzoj2178] 传送门: \(\text{CIRU - The area ...

  5. SPOJ 8073 The area of the union of circles(计算几何の圆并)(CIRU)

    Description You are given N circles and expected to calculate the area of the union of the circles ! ...

  6. SPOJ 8073 The area of the union of circles (圆并入门)

    Sphere Online Judge (SPOJ) - Problem CIRU [求圆并的若干种算法,圆并扩展算法]_AekdyCoin的空间_百度空间 参考AekdyCoin的圆并算法解释,根据 ...

  7. [SPOJ-CIRU]The area of the union of circles/[BZOJ2178]圆的面积并

    [SPOJ-CIRU]The area of the union of circles/[BZOJ2178]圆的面积并 题目大意: 求\(n(n\le1000)\)个圆的面积并. 思路: 对于一个\( ...

  8. SPOJ CIRU SPOJ VCIRCLE 圆的面积并问题

    SPOJ VCIRCLE SPOJ CIRU 两道题都是给出若干圆 就面积并,数据规模和精度要求不同. 求圆面积并有两种常见的方法,一种是Simpson积分,另一种是几何法. 在这里给出几何方法. P ...

  9. SPOJ CIRU

    SPOJ CIRU 题意 给出n个圆,求他们覆盖的面积. 解法 自适应Simpson,但需要将圆离散化一下,以保证我们查询的是一个连续的有圆的区间. 奇怪的是我没有离散化,样例都没有过,却把题给A了 ...

随机推荐

  1. [洛谷P3521][POI2011]ROT-Tree Rotations

    题目大意:给一棵$n(n\leqslant2\times10^5)$个叶子的二叉树,可以交换每个点的左右子树,要求前序遍历叶子的逆序对最少.输出最少的逆序对个数 题解:线段树合并,对于每个节点求出交换 ...

  2. POJ3020:Antenna Placement(二分图匹配)

    Antnna Placement Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11093   Accepted: 5459 ...

  3. python监控服务器

    import paramikoimport threadingimport reimport timeimport stringfrom sendmail import send_maildef ss ...

  4. nginx 设置ip地址访问,但是设置域名访问不了

    一.导语 在Nginx的设置过程中,ip地址能正常访问的,但是把ip地址转换成域名,就访问不了了,这个是怎么回事呢?今天来探讨一下 二.设置ip地址做负载均衡 2.1.server端 server { ...

  5. PHP设计模式-代理模式

    概念理解: 代理模式,是对简单处理程序(或指针)的增强,用于引用一个对象:这个指针被代理对象取代,代理对象位于客户端和真实程序之间,指针有一个可被多个目标利用的钩子. 参与者: client(参与者) ...

  6. CSS选择器及CSS3新增选择器

    转自:http://www.cnblogs.com/libingql/p/4375354.html 1. CSS1定义的选择器 选择器 类型 说明 E 类型选择器 选择指定类型的元素 E#id ID选 ...

  7. oracle导入和导出和授权

    导入数据库: imp demo@orcl file=d:/bak_1023.dmp full=y ignore=y 导出数据库: @orcl file=d:/bak_1023.dmpexp yhtj/ ...

  8. Visual Studio Code 配置C/C++环境

    0. 前言 VS Code 是微软发布一款跨平台的源代码编辑器,其拥有强大的功能和丰富的扩展,使之能适合编写许多语言. 本文面向初学者(但不是纯小白),分享一点我配置C/C++的经验. 本文所有内容均 ...

  9. 数学:乘法逆元-拓展GCD

    乘法逆元应用在组合数学取模问题中,这里给出的实现不见得好用 给出拓展GCD算法: 扩展欧几里得算法是指对于两个数a,b 一定能找到x,y(均为整数,但不满足一定是正数) 满足x*a+y*b=gcd(a ...

  10. [bzoj1251]序列终结者——splay

    题目大意 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技 ...