计算几何做题笔记
计算几何一生之敌!
凸多边形
凸多边形好啊!根据凸包的性质,凸多边形的核就是它自身。所以我们可以把凸包上的边变成半平面,这样也是表示凸多边形的一种方法吧...半平面可以求交,求出来的就是多边形的交啦。
1 # include <cstdio> 2 # include <iostream> 3 # include <cmath> 4 # include <algorithm> 5 # define R register int 6 7 using namespace std; 8 9 const int N=1005; 10 const double eps=1e-13; 11 int n,m,cnt,x[N],y[N]; 12 struct point 13 { 14 double x,y; 15 point (double a=0,double b=0) { x=a,y=b; } 16 }; 17 //感觉点和向量混用...也没什么关系吧 18 struct line //第一个点是起点,第二个点是终点; 19 { 20 point a,b; 21 line (point x=point(0,0),point y=point(0,0)) { a=x,b=y; } 22 }a[N],q[N]; 23 point p[N]; 24 25 double poa (line x) { return atan2(x.b.y-x.a.y,x.b.x-x.a.x); } 26 27 double cross (point a,point b) 28 { 29 return a.x*b.y-a.y*b.x; 30 } 31 32 point operator + (point a,point b) 33 { 34 return point(a.x+b.x,a.y+b.y); 35 } 36 37 point operator - (point a,point b) 38 { 39 return point(a.x-b.x,a.y-b.y); 40 } 41 42 point operator * (point a,double b) 43 { 44 return point(b*a.x,b*a.y); 45 } 46 47 bool cmp (line a,line b) 48 { 49 double p1=poa(a),p2=poa(b); 50 if(fabs(p1-p2)<eps) 51 return cross(a.b-a.a,b.b-a.a)>eps; //把最左边的放到最后,这样方便去重 52 return p1<p2; 53 } 54 55 point intersection (line a,line b) 56 { 57 double s1=cross(b.a-a.a,a.b-a.a),s2=cross(a.b-a.a,b.b-b.a); 58 double k=s1/s2; 59 return ((b.b-b.a)*k)+b.a; 60 } 61 62 bool rig (line a,line b,line c) 63 { 64 point x=intersection(b,c); 65 return (cross(a.b-a.a,x-a.a)<-eps); 66 } 67 68 double solve() 69 { 70 sort(a+1,a+1+cnt,cmp); 71 int h=1,t=0; n=0; 72 for (R i=1;i<cnt;++i) 73 { 74 if(fabs(poa(a[i])-poa(a[i+1]))<eps) continue; 75 a[++n]=a[i]; 76 } a[++n]=a[cnt]; 77 for (R i=1;i<=n;++i) 78 { 79 while(t-h+1>=2&&rig(a[i],q[t-1],q[t])) t--; 80 while(t-h+1>=2&&rig(a[i],q[h],q[h+1])) h++; 81 q[++t]=a[i]; 82 } 83 while(t-h+1>=2&&rig(q[h],q[t-1],q[t])) t--; 84 while(t-h+1>=2&&rig(q[t],q[h],q[h+1])) h++; 85 if(t-h+1>=3) 86 { 87 int tp=0; 88 q[t+1]=q[h]; 89 for (R i=h;i<=t;++i) 90 p[++tp]=intersection(q[i],q[i+1]); 91 double ans=0; 92 p[tp+1]=p[1]; 93 for (R i=1;i<=tp;++i) 94 ans+=cross(p[i],p[i+1]); 95 return max(ans,-ans)/2.0; 96 } 97 else return 0; 98 } 99 100 int main() 101 { 102 scanf("%d",&n); 103 for (R i=1;i<=n;++i) 104 { 105 scanf("%d",&m); 106 for (R j=1;j<=m;++j) 107 scanf("%d%d",&x[j],&y[j]); 108 for (R j=2;j<=m;++j) 109 a[++cnt]=line(point(x[j-1],y[j-1]),point(x[j],y[j])); 110 a[++cnt]=line(point(x[m],y[m]),point(x[1],y[1])); 111 } 112 printf("%.3lf\n",solve()); 113 return 0; 114 }
射箭