链接

2986是3675的简化版,只有一个三角形。

这题主要在于求剖分后三角形与圆的相交面积,需要分情况讨论。

具体可以看此博客 http://hi.baidu.com/billdu/item/703ad4e15d819db52f140b0b

在分析第3、4两种情况时,我是用角度来进行判断的,如果<obc||<ocb大于90度就为他所说的第四种情况,不然就是第三种情况。

还有对于sig的解释貌似网上都没写,可能都觉得太简单了。。。自己手画了一下,大体是这个样子的

poj2986A Triangle and a Circle&&poj3675Telescope(三角形剖分)红色标记那块三角形是需要减掉对于当前多边形,可以看出以最下角进行剖分三角形时,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 }
View Code

相关文章:

  • 2022-12-23
  • 2021-11-04
  • 2021-11-28
  • 2021-06-18
  • 2021-07-11
  • 2022-12-23
  • 2021-11-13
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-08-07
  • 2021-09-18
  • 2021-06-05
  • 2021-06-20
  • 2022-12-23
相关资源
相似解决方案