Description

Updog is watching a plane object with a telescope. The field of vision in the telescope can be described as a circle. The center is at the origin and the radius is R. The object can be seen as a simple polygon of N vertexes. Updog wants to know the area of the part of the object that can be seen in the telescope.

Input

The input will contain several test cases. For each case:
The first line contains only one real number R
The second line contains an integer N. The following N lines contain two real numbers xi and yi each, which describe the coordinates of a vertex. Two vertexes in adjacent lines are also adjacent on the polygon. 
Constraints: 3 ≤ N ≤50, 0.1 ≤ R ≤1000, -1000 ≤ xiyi ≤ 1000

Output

For each test case, output one real number on a separate line, which is the area of the part that can be seen. The result should be rounded to two decimal places.

 
题目大意:给一个圆心在原点的圆,半径为r。再给一个简单多边形,问这个简单多边形和圆的公共面积是多少。
思路:跟POJ2986一个思路,把简单多边形的每一个点和原点连线,就把这个多边形和圆的交变成了多个三角形与圆的交,根据有向面积的思路,加加减减就可以得到公共面积。
PS:所谓简单多边形,是指所有边都不相交的多边形。
PS2:之前求直线与圆的交点的时候,没留意到-EPS<delta<0,然后要求sqrt(delta)的情况……WA了很多很多次……计算几何真是可怕……
 
代码(0MS):
 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
#define sqr(x) ((x) * (x)) const int MAXN = ;
const double EPS = 1e-;
const double PI = acos(-1.0);//3.14159265358979323846
const double INF = ; inline int sgn(double x) {
return (x > EPS) - (x < -EPS);
} struct Point {
double x, y, ag;
Point() {}
Point(double x, double y): x(x), y(y) {}
void read() {
scanf("%lf%lf", &x, &y);
}
bool operator == (const Point &rhs) const {
return sgn(x - rhs.x) == && sgn(y - rhs.y) == ;
}
bool operator < (const Point &rhs) const {
if(y != rhs.y) return y < rhs.y;
return x < rhs.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 * (const double &b) const {
return Point(x * b, y * b);
}
Point operator / (const double &b) const {
return Point(x / b, y / b);
}
double operator * (const Point &rhs) const {
return x * rhs.x + y * rhs.y;
}
double length() {
return sqrt(x * x + y * y);
}
double angle() {
return atan2(y, x);
}
Point unit() {
return *this / length();
}
void makeAg() {
ag = atan2(y, x);
}
void print() {
printf("%.10f %.10f\n", x, y);
}
};
typedef Point Vector; double dist(const Point &a, const Point &b) {
return (a - b).length();
} double cross(const Point &a, const Point &b) {
return a.x * b.y - a.y * b.x;
}
//ret >= 0 means turn right
double cross(const Point &sp, const Point &ed, const Point &op) {
return cross(sp - op, ed - op);
} double area(const Point& a, const Point &b, const Point &c) {
return fabs(cross(a - c, b - c)) / ;
}
//counter-clockwise
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;
} double cosIncludeAngle(const Point &a, const Point &b, const Point &o) {
Point p1 = a - o, p2 = b - o;
return (p1 * p2) / (p1.length() * p2.length());
} double includedAngle(const Point &a, const Point &b, const Point &o) {
return acos(cosIncludeAngle(a, b, o));
/*
double ret = abs((a - o).angle() - (b - o).angle());
if(sgn(ret - PI) > 0) ret = 2 * PI - ret;
return ret;
*/
} struct Seg {
Point st, ed;
double ag;
Seg() {}
Seg(Point st, Point ed): st(st), ed(ed) {}
void read() {
st.read(); ed.read();
}
void makeAg() {
ag = atan2(ed.y - st.y, ed.x - st.x);
}
};
typedef Seg Line; //ax + by + c > 0
Line buildLine(double a, double b, double c) {
if(sgn(a) == && sgn(b) == ) return Line(Point(sgn(c) > ? - : , INF), Point(, INF));
if(sgn(a) == ) return Line(Point(sgn(b), -c/b), Point(, -c/b));
if(sgn(b) == ) return Line(Point(-c/a, ), Point(-c/a, sgn(a)));
if(b < ) return Line(Point(, -c/b), Point(, -(a + c) / b));
else return Line(Point(, -(a + c) / b), Point(, -c/b));
} void moveRight(Line &v, double r) {
double dx = v.ed.x - v.st.x, dy = v.ed.y - v.st.y;
dx = dx / dist(v.st, v.ed) * r;
dy = dy / dist(v.st, v.ed) * r;
v.st.x += dy; v.ed.x += dy;
v.st.y -= dx; v.ed.y -= dx;
} bool isOnSeg(const Seg &s, const Point &p) {
return (p == s.st || p == s.ed) ||
(((p.x - s.st.x) * (p.x - s.ed.x) < ||
(p.y - s.st.y) * (p.y - s.ed.y) < ) &&
sgn(cross(s.ed, p, s.st)) == );
} bool isInSegRec(const Seg &s, const Point &p) {
return sgn(min(s.st.x, s.ed.x) - p.x) <= && sgn(p.x - max(s.st.x, s.ed.x)) <=
&& sgn(min(s.st.y, s.ed.y) - p.y) <= && sgn(p.y - max(s.st.y, s.ed.y)) <= ;
} bool isIntersected(const Point &s1, const Point &e1, const Point &s2, const Point &e2) {
return (max(s1.x, e1.x) >= min(s2.x, e2.x)) &&
(max(s2.x, e2.x) >= min(s1.x, e1.x)) &&
(max(s1.y, e1.y) >= min(s2.y, e2.y)) &&
(max(s2.y, e2.y) >= min(s1.y, e1.y)) &&
(cross(s2, e1, s1) * cross(e1, e2, s1) >= ) &&
(cross(s1, e2, s2) * cross(e2, e1, s2) >= );
} bool isIntersected(const Seg &a, const Seg &b) {
return isIntersected(a.st, a.ed, b.st, b.ed);
} bool isParallel(const Seg &a, const Seg &b) {
return sgn(cross(a.ed - a.st, b.ed - b.st)) == ;
} //return Ax + By + C =0 's A, B, C
void Coefficient(const Line &L, double &A, double &B, double &C) {
A = L.ed.y - L.st.y;
B = L.st.x - L.ed.x;
C = L.ed.x * L.st.y - L.st.x * L.ed.y;
}
//point of intersection
Point operator * (const Line &a, const Line &b) {
double A1, B1, C1;
double A2, B2, C2;
Coefficient(a, A1, B1, C1);
Coefficient(b, A2, B2, C2);
Point I;
I.x = - (B2 * C1 - B1 * C2) / (A1 * B2 - A2 * B1);
I.y = (A2 * C1 - A1 * C2) / (A1 * B2 - A2 * B1);
return I;
} bool isEqual(const Line &a, const Line &b) {
double A1, B1, C1;
double A2, B2, C2;
Coefficient(a, A1, B1, C1);
Coefficient(b, A2, B2, C2);
return sgn(A1 * B2 - A2 * B1) == && sgn(A1 * C2 - A2 * C1) == && sgn(B1 * C2 - B2 * C1) == ;
} double Point_to_Line(const Point &p, const Line &L) {
return fabs(cross(p, L.st, L.ed)/dist(L.st, L.ed));
} double Point_to_Seg(const Point &p, const Seg &L) {
if(sgn((L.ed - L.st) * (p - L.st)) < ) return dist(p, L.st);
if(sgn((L.st - L.ed) * (p - L.ed)) < ) return dist(p, L.ed);
return Point_to_Line(p, L);
} double Seg_to_Seg(const Seg &a, const Seg &b) {
double ans1 = min(Point_to_Seg(a.st, b), Point_to_Seg(a.ed, b));
double ans2 = min(Point_to_Seg(b.st, a), Point_to_Seg(b.ed, a));
return min(ans1, ans2);
} struct Circle {
Point c;
double r;
Circle() {}
Circle(Point c, double r): c(c), r(r) {}
void read() {
c.read();
scanf("%lf", &r);
}
double area() const {
return PI * r * r;
}
bool contain(const Circle &rhs) const {
return sgn(dist(c, rhs.c) + rhs.r - r) <= ;
}
bool contain(const Point &p) const {
return sgn(dist(c, p) - r) <= ;
}
bool intersect(const Circle &rhs) const {
return sgn(dist(c, rhs.c) - r - rhs.r) < ;
}
bool tangency(const Circle &rhs) const {
return sgn(dist(c, rhs.c) - r - rhs.r) == ;
}
Point pos(double angle) const {
Point p = Point(c.x + r, c.y);
return rotate(p, angle, c);
}
}; double CommonArea(const Circle &A, const Circle &B) {
double area = 0.0;
const Circle & M = (A.r > B.r) ? A : B;
const Circle & N = (A.r > B.r) ? B : A;
double D = dist(M.c, N.c);
if((D < M.r + N.r) && (D > M.r - N.r)) {
double cosM = (M.r * M.r + D * D - N.r * N.r) / (2.0 * M.r * D);
double cosN = (N.r * N.r + D * D - M.r * M.r) / (2.0 * N.r * D);
double alpha = * acos(cosM);
double beta = * acos(cosN);
double TM = 0.5 * M.r * M.r * (alpha - sin(alpha));
double TN = 0.5 * N.r * N.r * (beta - sin(beta));
area = TM + TN;
}
else if(D <= M.r - N.r) {
area = N.area();
}
return area;
} int intersection(const Seg &s, const Circle &cir, Point &p1, Point &p2) {
double angle = cosIncludeAngle(s.ed, cir.c, s.st);
//double angle1 = cos(includedAngle(s.ed, cir.c, s.st));
double B = dist(cir.c, s.st);
double a = , b = - * B * angle, c = sqr(B) - sqr(cir.r);
double delta = sqr(b) - * a * c;
if(sgn(delta) < ) return ;
if(sgn(delta) == ) delta = ;
double x1 = (-b - sqrt(delta)) / ( * a), x2 = (-b + sqrt(delta)) / ( * a);
Vector v = (s.ed - s.st).unit();
p1 = s.st + v * x1;
p2 = s.st + v * x2;
return + sgn(delta);
} double CommonArea(const Circle &cir, Point p1, Point p2) {
if(p1 == cir.c || p2 == cir.c) return ;
if(cir.contain(p1) && cir.contain(p2)) {
return area(cir.c, p1, p2);
} else if(!cir.contain(p1) && !cir.contain(p2)) {
Point q1, q2;
int t = intersection(Line(p1, p2), cir, q1, q2);
if(t == ) {
double angle = includedAngle(p1, p2, cir.c);
return 0.5 * sqr(cir.r) * angle;
} else {
double angle1 = includedAngle(p1, p2, cir.c);
double angle2 = includedAngle(q1, q2, cir.c);
if(isInSegRec(Seg(p1, p2), q1))return 0.5 * sqr(cir.r) * (angle1 - angle2 + sin(angle2));
else return 0.5 * sqr(cir.r) * angle1;
}
} else {
if(cir.contain(p2)) swap(p1, p2);
Point q1, q2;
intersection(Line(p1, p2), cir, q1, q2);
double angle = includedAngle(q2, p2, cir.c);
double a = area(cir.c, p1, q2);
double b = 0.5 * sqr(cir.r) * angle;
return a + b;
}
} struct Triangle {
Point p[];
Triangle() {}
Triangle(Point *t) {
for(int i = ; i < ; ++i) p[i] = t[i];
}
void read() {
for(int i = ; i < ; ++i) p[i].read();
}
double area() const {
return ::area(p[], p[], p[]);
}
Point& operator[] (int i) {
return p[i];
}
}; double CommonArea(Triangle tir, const Circle &cir) {
double ret = ;
ret += sgn(cross(tir[], cir.c, tir[])) * CommonArea(cir, tir[], tir[]);
ret += sgn(cross(tir[], cir.c, tir[])) * CommonArea(cir, tir[], tir[]);
ret += sgn(cross(tir[], cir.c, tir[])) * CommonArea(cir, tir[], tir[]);
return abs(ret);
} struct Poly {
int n;
Point p[MAXN];//p[n] = p[0]
void init(Point *pp, int nn) {
n = nn;
for(int i = ; i < n; ++i) p[i] = pp[i];
p[n] = p[];
}
double area() {
if(n < ) return ;
double s = p[].y * (p[n - ].x - p[].x);
for(int i = ; i < n; ++i)
s += p[i].y * (p[i - ].x - p[i + ].x);
return s / ;
}
};
//the convex hull is clockwise
void Graham_scan(Point *p, int n, int *stk, int &top) {//stk[0] = stk[top]
sort(p, p + n);
top = ;
stk[] = ; stk[] = ;
for(int i = ; i < n; ++i) {
while(top && cross(p[i], p[stk[top]], p[stk[top - ]]) <= ) --top;
stk[++top] = i;
}
int len = top;
stk[++top] = n - ;
for(int i = n - ; i >= ; --i) {
while(top != len && cross(p[i], p[stk[top]], p[stk[top - ]]) <= ) --top;
stk[++top] = i;
}
}
//use for half_planes_cross
bool cmpAg(const Line &a, const Line &b) {
if(sgn(a.ag - b.ag) == )
return sgn(cross(b.ed, a.st, b.st)) < ;
return a.ag < b.ag;
}
//clockwise, plane is on the right
bool half_planes_cross(Line *v, int vn, Poly &res, Line *deq) {
int i, n;
sort(v, v + vn, cmpAg);
for(i = n = ; i < vn; ++i) {
if(sgn(v[i].ag - v[i-].ag) == ) continue;
v[n++] = v[i];
}
int head = , tail = ;
deq[] = v[], deq[] = v[];
for(i = ; i < n; ++i) {
if(isParallel(deq[tail - ], deq[tail]) || isParallel(deq[head], deq[head + ]))
return false;
while(head < tail && sgn(cross(v[i].ed, deq[tail - ] * deq[tail], v[i].st)) > )
--tail;
while(head < tail && sgn(cross(v[i].ed, deq[head] * deq[head + ], v[i].st)) > )
++head;
deq[++tail] = v[i];
}
while(head < tail && sgn(cross(deq[head].ed, deq[tail - ] * deq[tail], deq[head].st)) > )
--tail;
while(head < tail && sgn(cross(deq[tail].ed, deq[head] * deq[head + ], deq[tail].st)) > )
++head;
if(tail <= head + ) return false;
res.n = ;
for(i = head; i < tail; ++i)
res.p[res.n++] = deq[i] * deq[i + ];
res.p[res.n++] = deq[head] * deq[tail];
res.n = unique(res.p, res.p + res.n) - res.p;
res.p[res.n] = res.p[];
return true;
} //ix and jx is the points whose distance is return, res.p[n - 1] = res.p[0], res must be clockwise
double dia_rotating_calipers(Poly &res, int &ix, int &jx) {
double dia = ;
int q = ;
for(int i = ; i < res.n - ; ++i) {
while(sgn(cross(res.p[i], res.p[q + ], res.p[i + ]) - cross(res.p[i], res.p[q], res.p[i + ])) > )
q = (q + ) % (res.n - );
if(sgn(dist(res.p[i], res.p[q]) - dia) > ) {
dia = dist(res.p[i], res.p[q]);
ix = i; jx = q;
}
if(sgn(dist(res.p[i + ], res.p[q]) - dia) > ) {
dia = dist(res.p[i + ], res.p[q]);
ix = i + ; jx = q;
}
}
return dia;
}
//a and b must be clockwise, find the minimum distance between two convex hull
double half_rotating_calipers(Poly &a, Poly &b) {
int sa = , sb = ;
for(int i = ; i < a.n; ++i) if(sgn(a.p[i].y - a.p[sa].y) < ) sa = i;
for(int i = ; i < b.n; ++i) if(sgn(b.p[i].y - b.p[sb].y) < ) sb = i;
double tmp, ans = dist(a.p[], b.p[]);
for(int i = ; i < a.n; ++i) {
while(sgn(tmp = cross(a.p[sa], a.p[sa + ], b.p[sb + ]) - cross(a.p[sa], a.p[sa + ], b.p[sb])) > )
sb = (sb + ) % (b.n - );
if(sgn(tmp) < ) ans = min(ans, Point_to_Seg(b.p[sb], Seg(a.p[sa], a.p[sa + ])));
else ans = min(ans, Seg_to_Seg(Seg(a.p[sa], a.p[sa + ]), Seg(b.p[sb], b.p[sb + ])));
sa = (sa + ) % (a.n - );
}
return ans;
} double rotating_calipers(Poly &a, Poly &b) {
return min(half_rotating_calipers(a, b), half_rotating_calipers(b, a));
} /*******************************************************************************************/ Point p[MAXN];
Circle cir;
double r;
int n; int main() {
while(scanf("%lf", &r) != EOF) {
scanf("%d", &n);
for(int i = ; i < n; ++i) p[i].read();
p[n] = p[];
cir = Circle(Point(, ), r);
double ans = ;
for(int i = ; i < n; ++i)
ans += sgn(cross(p[i], Point(, ), p[i + ])) * CommonArea(cir, p[i], p[i + ]);
printf("%.2f\n", fabs(ans));
}
}

POJ 3675 Telescope(简单多边形和圆的面积交)的更多相关文章

  1. POJ 3675 Telescope 简单多边形和圆的面积交

    这道题得控制好精度,不然会贡献WA  QAQ 还是那个规则: int sgn(double x){ if(x > eps) return 1; else if(x < - eps) ret ...

  2. POJ 3675 Telescope

    题意:给定一个不自交的多边形,要求和圆心在原点的圆的面积交. 思路:同POJ2986,是加强版 代码: #include<algorithm> #include<cstdio> ...

  3. poj 3675 Telescope (圆与多边形面积交)

    3675 -- Telescope 再来一题.这题的代码还是继续完全不看模板重写的. 题意不解释了,反正就是一个单纯的圆与多边形的交面积. 这题的精度有点搞笑.我用比较高的精度来统计面积,居然wa了. ...

  4. poj3675 求多边形与圆的面积交

    题意:给出多边形的顶点坐标.圆的圆心坐标和半径,求面积交 sol:又是模板题啦= = 注意poj的C++好像认不出hypot函数,要稍微改写一下. hypot(double x,double y):即 ...

  5. hdu 5120 Intersection 两个圆的面积交

    Intersection Time Limit: 4000/4000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others) P ...

  6. HDU 5120 Intersection (圆的面积交)

    题意:给定两个圆环,求两个圆环的面积交. 析:很容易知道,圆环面积交就是,大圆与大圆面积交 - 大圆和小圆面积交 - 小圆和大圆面积交 + 小圆和小圆面积交. 代码如下: #pragma commen ...

  7. HDU - 2892:area (圆与多边形交 求面积)

    pro:飞行员去轰炸一个小岛,给出炸弹落地点的位置信息,以及轰炸半径:按顺时针或者逆时针给出小岛的边界点. 求被轰炸的小岛面积. sol:即是求圆和多边形的面积交. (只会套板子的我改头换面,先理解然 ...

  8. Harry Potter and J.K.Rowling(半平面交+圆和矩形交)

    Harry Potter and J.K.Rowling http://acm.hdu.edu.cn/showproblem.php?pid=3982 Time Limit: 2000/1000 MS ...

  9. poj 2546(两圆公共面积)

    Circular Area Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5682   Accepted: 2225 Des ...

随机推荐

  1. OC中property方法的使用

    我们直入主题,关于property方法,我们先来了解一下相关的知识,首先是成员变量,实例变量,属性变量. 我们定义一个类来看一下 @interface Person :NSObject{ NSInte ...

  2. 840. Magic Squares In Grid (5月27日)

    开头 这是每周比赛中的第一道题,博主试了好几次坑后才勉强做对了,第二道题写的差不多结果去试时结果比赛已经已经结束了(尴尬),所以今天只记录第一道题吧 题目原文 Magic Squares In Gri ...

  3. 关于linux‘RedHat6.9在VMware虚拟机中的安装步骤

    redhat支持多种安装方式:光盘安装,硬盘安装和网络安装等,可以根据个人的实际情况来选择.我在这里选择的是光盘安装的方式安装RHEL6.9.(以下简称6.9) 1.首先准备好6.9的光盘镜像,在安装 ...

  4. React 父子组件和非父子组件传值

      零.this.props     可以接收到 外界的传值 和 此组件标签内部自定义的方法       例:         <one vals={message} sendVal={this ...

  5. MySQL 参数slave_pending_jobs_size_max设置

    今天生产环境上从库出现SQL进程停止的异常,错误信息如下: Slave_IO_Running: Yes Slave_SQL_Running: No Replicate_Do_DB: Replicate ...

  6. 对QP中RTC的理解

    1.概念 RTC(Run To Completion)是运行到完成为止的意思.在状态机中,从源状态到目标状态的转换动作要运行到完成. 从字面上来看,这个过程像是不可中断的,但实际并不是,这个过程可以被 ...

  7. Linux字符设备学习,总结

    注册字符驱动的一种老方法: 注册一个字符设备的经典方法是使用:int register_chrdev(unsigned int major, const char *name, structfile_ ...

  8. 『Python题库 - 简答题』 Python中的基本概念 (121道)

    ## 『Python题库 - 简答题』 Python中的基本概念 1. Python和Java.PHP.C.C#.C++等其他语言的对比? 2. 简述解释型和编译型编程语言? 3. 代码中要修改不可变 ...

  9. Python值集合操作

    list_l1 = [12,1,4,6,9,5,4,2,11] list_l1 = set(list_l1) print(list_l1,type(list_l1)) #集合也是无序的 list_2 ...

  10. 为什么我要放弃javaScript数据结构与算法(第五章)—— 链表

    这一章你将会学会如何实现和使用链表这种动态的数据结构,这意味着我们可以从中任意添加或移除项,它会按需进行扩张. 本章内容 链表数据结构 向链表添加元素 从链表移除元素 使用 LinkedList 类 ...