Sphere Online Judge (SPOJ) - Problem CIRU

【求圆并的若干种算法,圆并扩展算法】_AekdyCoin的空间_百度空间

  参考AekdyCoin的圆并算法解释,根据理解写出的代码。圆并这么多题中,最基础一题。

  操作如下:

(1)对一个圆,获得所有与其他圆的交点作为时间戳。

  a.如果这个圆不被其他任何圆覆盖,这个圆直接保留。

  b.如果Case中有两个完全重合的圆,可以保留标号小(或大)的圆,也只保留这一个。

(2)每经过一个时间戳就对计数器加减,如果计数器从0变1,加上这段圆弧和对应的三角形。

(3)所有这样的圆独立计算,最后求出的面积累加即可。

代码如下(1y):

 #include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm> using namespace std; const double PI = acos(-1.0);
const double EPS = 1e-;
inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
template<class T> T sqr(T x) { return x * x;}
typedef pair<double, double> Point;
#define x first
#define y second
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);} inline double cross(Point a, Point b) { return a.x * b.y - a.y * b.x;}
inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y;}
inline double angle(Point a) { return atan2(a.y, a.x);}
inline double veclen(Point a) { return sqrt(dot(a, a));} struct Circle {
Point c;
double r;
Circle() {}
Circle(Point c, double r) : c(c), r(r) {}
Point point(double p) { return Point(c.x + r * cos(p), c.y + r * sin(p));}
void get() { scanf("%lf%lf%lf", &c.x, &c.y, &r);}
} ; bool ccint(Circle a, Circle b, double &a1, double &a2) { // ips for Circle-a (anti-clockwise p1->p2)
double d = veclen(a.c - b.c);
double r1 = a.r, r2 = b.r;
if (sgn(d - r1 - r2) >= ) return ;
if (sgn(fabs(r1 - r2) - d) >= ) return ;
double da = acos((sqr(d) + sqr(r1) - sqr(r2)) / ( * d * r1));
double ang = angle(b.c - a.c);
a1 = ang - da, a2 = ang + da;
return ;
} const int N = ;
Circle cir[N]; inline double gettri(Point o, Point a, Point b) { return cross(a - o, b - o) / ;}
inline double getarc(Circle o, double a, double b) { return (b - a) * sqr(o.r) / - gettri(o.c, o.point(a), o.point(b));} typedef pair<double, int> Event;
Event ev[N << ]; bool inside(int a, int n) {
double d, r1, r2;
for (int i = ; i < n; i++) {
if (i == a) continue;
d = veclen(cir[i].c - cir[a].c);
r1 = cir[i].r, r2 = cir[a].r;
if (sgn(r1 - r2) == && sgn(fabs(r1 - r2) - d) == ) {
if (i > a) return ;
continue;
}
if (sgn(r1 - r2) >= && sgn(fabs(r1 - r2) - d) >= ) return ;
}
return ;
} double getarea(int a, int n) {
if (inside(a, n)) return ;
Circle &c = cir[a];
double ret = ;
double a1, a2;
Point p1, p2;
int tt = ;
for (int i = ; i < n; i++) {
if (i == a) continue;
if (ccint(c, cir[i], a1, a2)) {
if (a2 > PI) ev[tt++] = Event(a1, ), ev[tt++] = Event(PI, -), ev[tt++] = Event(-PI, ), ev[tt++] = Event(a2 - * PI, -);
else if (a1 < -PI) ev[tt++] = Event(a1 + * PI, ), ev[tt++] = Event(PI, -), ev[tt++] = Event(-PI, ), ev[tt++] = Event(a2, -);
else ev[tt++] = Event(a1, ), ev[tt++] = Event(a2, -);
}
}
if (tt == ) return PI * sqr(c.r);
sort(ev, ev + tt);
int cnt = ;
double last = -PI;
for (int i = ; i < tt; i++) {
double cur = ev[i].x;
if (ev[i].y == && cnt == ) ret += getarc(c, last, cur) + cross(c.point(last), c.point(cur)) / ;
cnt += ev[i].y;
last = cur;
}
ret += getarc(c, last, PI) + cross(c.point(last), c.point(PI)) / ;
return ret;
} double work(int n) {
double ret = ;
for (int i = ; i < n; i++) ret += getarea(i, n);
return ret;
} int main() {
int n;
while (~scanf("%d", &n)) {
for (int i = ; i < n; i++) cir[i].get();
printf("%.3f\n", work(n));
}
return ;
}

——written by Lyon

SPOJ 8073 The area of the union of circles (圆并入门)的更多相关文章

  1. 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 ! ...

  2. SPOJ CIRU - The area of the union of circles (圆的面积并)

    CIRU - The area of the union of circles no tags  You are given N circles and expected to calculate t ...

  3. 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 ...

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

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

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

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

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

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

  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. POJ1151Atlantis 矩形面积并[线段树 离散化 扫描线]

    Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 21734   Accepted: 8179 Descrip ...

随机推荐

  1. PHP生成linux命令行进度条

    <?php$total = 100; for ($i = 1; $i <= $total; $i++) { printf("progress: [%-50s] %d%% Done ...

  2. CSS min-height 属性

    实例 设置段落的最小高度: p { min-height:100px; } 浏览器支持 IE Firefox Chrome Safari Opera 所有主流浏览器都支持 min-height 属性. ...

  3. vagrant简介

    什么是vagrant? 简单理解,就是可以通过Vagrant这个工具管理虚拟机,比如说想创建一个centos环境的虚拟机,不需要安装系统这么麻烦,通过vagrant可以快速创建 官网地址:https: ...

  4. uptime查看服务器运行时间

    uptime命令用于查看服务器运行了多长时间以及有多少个用户登录,快速获知服务器的负荷情况. uptime的输出包含一项内容是load average,显示了最近1,5,15分钟的负荷情况.它的值代表 ...

  5. NOIP2016参赛日志+总结

    这个故事告诉我们,成绩出来之前一定要装弱.这些文字是作者拿到程序后测了洛谷民间数据后写的. 2016.11.18  Day    0 早上五点半起床,洗漱完毕,吃了早饭,收拾收拾,七点半从家出发,去了 ...

  6. 洛谷 USACO P2207 Photo

    P2207 Photo 题目描述 Framer Jhon 打算给他的N头奶牛照相,( 2 <= N <= 1 000 000 000) . 他们排成一条线,并且依次取1~N作为编号. 每一 ...

  7. Leetcode641.Design Circular Deque设计循环双端队列

    设计实现双端队列. 你的实现需要支持以下操作: MyCircularDeque(k):构造函数,双端队列的大小为k. insertFront():将一个元素添加到双端队列头部. 如果操作成功返回 tr ...

  8. Django 的逆向解析url(转)

    Django中提供了一个关于URL的映射的解决方案,你可以做两个方向的使用: 1.有客户端的浏览器发起一个url请求,Django根据URL解析,把url中的参数捕获,调用相应的试图, 获取相应的数据 ...

  9. IO流-文件操作

    一.字节流读/写 文件 1.字节流 方式读取文件

  10. 将CMD命令提示符的起始位置进行更改 / CMD起始位置发生改变后如何修改回来

    具体步骤如下: 1.首先我们需要先找到命令提示符所在的文件目录.可以在开始运行程序中输入CMD,一般回自动搜索匹配. 2.右键点击命令提示符,在弹出菜单中,选择“打开文件位置”: 3.然后我们就可以进 ...