2986是3675的简化版,只有一个三角形。
这题主要在于求剖分后三角形与圆的相交面积,需要分情况讨论。
具体可以看此博客 http://hi.baidu.com/billdu/item/703ad4e15d819db52f140b0b
在分析第3、4两种情况时,我是用角度来进行判断的,如果<obc||<ocb大于90度就为他所说的第四种情况,不然就是第三种情况。
还有对于sig的解释貌似网上都没写,可能都觉得太简单了。。。自己手画了一下,大体是这个样子的
红色标记那块三角形是需要减掉对于当前多边形,可以看出以最下角进行剖分三角形时,cross(b,c)算的那块小三角形的确是负的,所以需要判断一下当前的面积是要加上的还是要减掉的。
讨论的东西比较多,细节比较多,WA了好多遍,对着数据查了好久终于过了。。
附上一些数据
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 struct point 18 { 19 double x,y; 20 point(double x=0,double y=0):x(x),y(y) {} 21 } p[N]; 22 struct tri 23 { 24 point a,b,c; 25 } tr[N]; 26 typedef point pointt; 27 point operator -(point a,point b) 28 { 29 return point(a.x-b.x,a.y-b.y); 30 } 31 point operator *(point a,double r) 32 { 33 return point(a.x*r,a.y*r); 34 } 35 point operator +(point a,point b) 36 { 37 return point(a.x+b.x,a.y+b.y); 38 } 39 struct line 40 { 41 point u,v; 42 point ppoint(double t) 43 { 44 return point(u+v*t); 45 } 46 }; 47 struct circle 48 { 49 point c; 50 double r; 51 circle(point c,double r):c(c),r(r) {} 52 point ppoint(double a) 53 { 54 return point(c.x+cos(a)*r,c.y+sin(a)*r); 55 } 56 }; 57 double r; 58 point ip; 59 double dcmp(double x) 60 { 61 if(fabs(x)<eps) return 0; 62 return x<0?-1:1; 63 } 64 double dis(point a) 65 { 66 return sqrt(a.x*a.x+a.y*a.y); 67 } 68 double dot(point a,point b) 69 { 70 return a.x*b.x+a.y*b.y; 71 } 72 double cross(point a,point b) 73 { 74 return a.x*b.y-a.y*b.x; 75 } 76 double area(point a,point b,point c) 77 { 78 return fabs(cross(a-c,b-c))/2; 79 } 80 81 int getlinecircle(line ll,circle cc,point &p1,point &p2) 82 { 83 double a = ll.v.x,b = ll.u.x-cc.c.x,c = ll.v.y,d = ll.u.y-cc.c.y; 84 double e = a*a+c*c,f = 2*(a*b+c*d),g = b*b+d*d-cc.r*cc.r; 85 double delta = f*f-4*e*g; 86 double t1,t2; 87 if(dcmp(delta)<0)return 0;//ÏàÀë 88 if(dcmp(delta)==0) 89 { 90 t1 = t2 = -f/(2*e);//cout<<t1<<" -"<<e<<" "<<f<<endl; 91 p1 = ll.ppoint(t1); 92 return 1;//ÏàÇÐ 93 } 94 //Ïཻ 95 t1 = (-f-sqrt(delta))/(2*e); 96 p1 = ll.ppoint(t1); 97 t2 = (-f+sqrt(delta))/(2*e); 98 p2 = ll.ppoint(t2); 99 // cout<<p1.x<<" "<<p1.y<<" "<<p2.x<<" "<<p2.y<<endl; 100 return 2; 101 } 102 double mul(point a,point b,point c) 103 { 104 return cross(b-a,c-a); 105 } 106 bool cmp(point a,point b) 107 { 108 if(dcmp(mul(ip,a,b))==0) 109 return dis(a-ip)<dis(b-ip); 110 else 111 return dcmp(mul(ip,a,b))>0; 112 } 113 double distancetoline(point p,point a,point b) 114 { 115 point v1 = a-b,v2 = p-b; 116 return fabs(cross(v1,v2))/dis(v1); 117 } 118 int dot_online_in(point p,point l1,point l2) 119 { 120 return !dcmp(mul(p,l1,l2))&&(l1.x-p.x)*(l2.x-p.x)<eps&&(l1.y-p.y)*(l2.y-p.y)<eps; 121 } 122 double angle(point a,point b) 123 { 124 return acos(dot(a,b)/dis(a)/dis(b)); 125 } 126 double cal(tri tr) 127 { 128 circle cp=circle(point(0,0),r); 129 int sig = dcmp(cross(tr.b,tr.c)); 130 if(sig==0) return 0; 131 double d1 = dis(tr.a-tr.b),d2 = dis(tr.a-tr.c); 132 if(dcmp(d1-r)<=0&&dcmp(d2-r)<=0) 133 { 134 double s = sig*area(tr.a,tr.b,tr.c); 135 return s; 136 } 137 double dline = distancetoline(cp.c,tr.b,tr.c); 138 if(dcmp(d1-r)>=0&&dcmp(d2-r)>=0&&dcmp(dline-r)>=0) 139 { 140 return sig*angle(tr.b,tr.c)*r*r/2.0; 141 } 142 double ag = angle(tr.c-tr.b,tr.a-tr.b),bg = angle(tr.b-tr.c,tr.a-tr.c); 143 point p1,p2; 144 line l1; 145 l1.u = tr.b,l1.v = tr.c-tr.b; 146 getlinecircle(l1,cp,p1,p2); 147 148 if(dcmp(d1-r)>=0&&dcmp(d2-r)>=0&&dcmp(dline-r)<0&&(dcmp(ag-pi/2)>=0||dcmp(bg-pi/2)>=0)) 149 { 150 151 double s = sig*angle(tr.b,tr.c)*r*r/2; 152 return s; 153 } 154 if(dcmp(d1-r)>=0&&dcmp(d2-r)>=0&&dcmp(dline-r)<0) 155 { 156 double s = (angle(tr.b,tr.c)-angle(p1,p2))*r*r/2.0+area(tr.a,p1,p2); 157 return sig*s; 158 } 159 160 p1 = dot_online_in(p1,tr.b,tr.c)?p1:p2; 161 if(dcmp(d1-r)<0) 162 { 163 return sig*(angle(tr.c,p1)*r*r/2+area(tr.a,p1,tr.b)); 164 } 165 else 166 { 167 return sig*(angle(p1,tr.b)*r*r/2+area(tr.a,p1,tr.c)); 168 } 169 } 170 int dots_inline(point p1,point p2,point p3) 171 { 172 return !dcmp(mul(p1,p2,p3)); 173 } 174 int main() 175 { 176 int i,n; 177 while(scanf("%lf",&r)!=EOF) 178 { 179 scanf("%d",&n); 180 for(i = 0; i < n ; i++) 181 { 182 scanf("%lf%lf",&p[i].x,&p[i].y); 183 } 184 p[n] = p[0]; 185 double ans = 0; 186 for(i = 0 ; i < n ; i++) 187 { 188 if(dots_inline(ip,p[i],p[i+1])) continue; 189 tr[i].a = point(0,0); 190 tr[i].b = p[i]; 191 tr[i].c = p[i+1]; 192 ans+=cal(tr[i]); 193 } 194 printf("%.2f\n",fabs(ans)+eps); 195 } 196 return 0; 197 }