题目:http://poj.org/problem?id=1279
题意:求多边形内的一块区域,从这块区域可以看到多边形的所有角落,求这块区域的面积
分析:这题其实就是求多边形的核的面积,套用半平面交的模板,再用上多边形面积公式即可
代码:
#include<cmath> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int mm=2222; typedef double DIY; struct point { DIY x,y; point(){} point(DIY _x,DIY _y):x(_x),y(_y){} }g[mm]; point MakeVector(point &P,point &Q) { return point(Q.x-P.x,Q.y-P.y); } DIY CrossProduct(point P,point Q) { return P.x*Q.y-P.y*Q.x; } DIY MultiCross(point P,point Q,point R) { return CrossProduct(MakeVector(Q,P),MakeVector(Q,R)); } struct halfPlane { point s,t; double angle; halfPlane(){} halfPlane(point _s,point _t):s(_s),t(_t){} halfPlane(DIY sx,DIY sy,DIY tx,DIY ty):s(sx,sy),t(tx,ty){} void GetAngle() { angle=atan2(t.y-s.y,t.x-s.x); } }hp[mm],q[mm]; point IntersectPoint(halfPlane P,halfPlane Q) { DIY a1=CrossProduct(MakeVector(P.s,Q.t),MakeVector(P.s,Q.s)); DIY a2=CrossProduct(MakeVector(P.t,Q.s),MakeVector(P.t,Q.t)); return point((P.s.x*a2+P.t.x*a1)/(a2+a1),(P.s.y*a2+P.t.y*a1)/(a2+a1)); } bool cmp(halfPlane P,halfPlane Q) { if(fabs(P.angle-Q.angle)<1e-8) return MultiCross(P.s,P.t,Q.s)>0; return P.angle<Q.angle; } bool IsParallel(halfPlane P,halfPlane Q) { return fabs(CrossProduct(MakeVector(P.s,P.t),MakeVector(Q.s,Q.t)))<1e-8; } void HalfPlaneIntersect(int n,int &m) { sort(hp,hp+n,cmp); int i,l=0,r=1; for(m=i=1;i<n;++i) if(hp[i].angle-hp[i-1].angle>1e-8)hp[m++]=hp[i]; n=m; m=0; q[0]=hp[0],q[1]=hp[1]; for(i=2;i<n;++i) { if(IsParallel(q[r],q[r-1])||IsParallel(q[l],q[l+1]))return; while(l<r&&MultiCross(hp[i].s,hp[i].t,IntersectPoint(q[r],q[r-1]))>0)--r; while(l<r&&MultiCross(hp[i].s,hp[i].t,IntersectPoint(q[l],q[l+1]))>0)++l; q[++r]=hp[i]; } while(l<r&&MultiCross(q[l].s,q[l].t,IntersectPoint(q[r],q[r-1]))>0)--r; while(l<r&&MultiCross(q[r].s,q[r].t,IntersectPoint(q[l],q[l+1]))>0)++l; q[++r]=q[l]; for(i=l;i<r;++i) g[m++]=IntersectPoint(q[i],q[i+1]); } int main() { int i,n,m,t; double ans; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=0;i<n;++i) scanf("%lf%lf",&g[i].x,&g[i].y); g[n]=g[0]; for(i=0;i<n;++i) { hp[i]=halfPlane(g[i+1],g[i]); hp[i].GetAngle(); } HalfPlaneIntersect(n,m); ans=0; if(m>2) { g[m]=g[0]; for(i=0;i<m;++i) ans+=CrossProduct(g[i],g[i+1]); if(ans<0)ans=-ans; } printf("%.2lf\n",ans/2.0); } return 0; }