1 /*
2 代码:(转)http://blog.csdn.net/u010527492/article/details/18190147
3 题解:(转)http://hi.baidu.com/billdu/item/703ad4e15d819db52f140b0b
4 */
5 #include<cstdio>
6 #include<algorithm>
7 #include<cmath>
8
9 const double eps = 1e-8;
10
11 using namespace std;
12
13 struct point{
14 double x,y;
15 point(){}
16 point(double x_,double y_):x(x_),y(y_){}
17 }p[58];
18
19 double r; // 所求圆半径
20 point origin; // 所求圆圆心
21
22 int n;
23 double MIN(double x,double y){ return x<y?x:y; }
24 double MAX(double x,double y){ return x>y?x:y; }
25
26 double cross(point p1,point p2,point p3) {
27 return (p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y);
28 }
29 double dot(point p1,point p2) {
30 return p1.x*p2.x+p1.y*p2.y;
31 }
32 double getdis(point p1,point p2) {
33 return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
34 }
35
36 point get_intersect(point a, point b) { // 线段与圆的交点
37 point temp=point(a.x-b.x,a.y-b.y);
38 point vec=point(temp.y,-temp.x);
39 point origin2=point(origin.x+vec.x,origin.y+vec.y);
40 double a1=a.y-b.y;
41 double b1=b.x-a.x;
42 double c1=(a.x*b.y-b.x*a.y);
43
44 double a2=origin.y-origin2.y;
45 double b2=origin2.x-origin.x;
46 double c2=(origin.x*origin2.y-origin2.x*origin.y);
47
48 double cc=a1*b2-a2*b1;
49 return point((b1*c2-b2*c1)/cc,(a2*c1-a1*c2)/cc);
50 };
51
52 int on_line(point p0,point p1,point p2) { // 点p0是否在线段p1-p2上
53 if(p0.x>MAX(p1.x,p2.x)) return 0;
54 if(p0.x<MIN(p1.x,p2.x)) return 0;
55 if(p0.y>MAX(p1.y,p2.y)) return 0;
56 if(p0.y<MIN(p1.y,p2.y)) return 0;
57 return 1;
58 }
59 double get_area(point a, point b) { // 获取某点为圆心的三角形与该圆的相交面积
60 double disa = getdis(origin,a);
61 double disb = getdis(origin,b);
62
63 double angle = acos(dot(a,b)/disa/disb); // 求两向量夹角
64 point inter = get_intersect(a,b);
65 double disinter = getdis(inter,origin);
66 double sgn = cross(origin,a,b) < 0 ? -1 : 1;
67 double ret = 0;
68
69 if(angle < eps || fabs(cross(origin,a,b)) < eps)
70 return 0;
71 else if(disa < r+eps && disb < r+eps) { // 线段在圆内或圆上
72 ret = fabs(cross(origin,a,b))/2.0;
73 }
74 else if(disa < r-eps || disb < r-eps) { // 线段的一端在圆内
75 if(disb < r-eps) {
76 swap(a,b);
77 swap(disa,disb);
78 }
79 double disab = getdis(a,b);
80 point mov = point((b.x-a.x)/disab,(b.y-a.y)/disab);
81 double len = sqrt(r*r-disinter*disinter);
82 point interpoint;
83 interpoint = point(inter.x+mov.x*len, inter.y+mov.y*len);
84 double angle0 = acos(dot(b,interpoint)/disb/r);
85 ret = r*r*angle0/2.0;
86 ret += fabs(cross(origin,interpoint,a))/2.0;
87 }
88 else {
89 int flag = on_line(inter,a,b);
90 ret = r*r*angle/2.0;
91 if(flag && disinter<r)
92 {
93 double tangle = 2*acos(disinter/r);
94 ret -= r*r*tangle/2.0;
95 ret += r*disinter*sin(tangle/2.0);
96 }
97 }
98 return ret*sgn;
99 }
100 double solve(point center)
101 {
102 double ret = 0;
103 for(int i=1;i<=n;i++) {
104 point a,b;
105 a.x = p[i].x - center.x;
106 a.y = p[i].y - center.y;
107 b.x = p[i+1].x - center.x;
108 b.y = p[i+1].y - center.y;
109 ret += get_area(a,b);
110 }
111 return ret;
112 }
113 int main(void)
114 {
115 origin = point(0,0);
116 while(~scanf("%lf%d",&r,&n))
117 {
118 for(int i=1;i<=n;i++)
119 {
120 scanf("%lf%lf",&p[i].x,&p[i].y);
121 p[i].x++; // +1是为了测试一下代码
122 p[i].y++;
123 }
124 p[n+1]=p[1];
125 point tmp;
126 tmp.x = 1;
127 tmp.y = 1;
128 printf("%.2lf\n",fabs(solve(tmp)));
129 }
130 return 0;
131 }