分析:题目就是让你求多边形的核的面积,多边形的核就相当于在某一点能看到所有顶点(不穿过边),这些点的集合就是多边形的核。
如果有不懂地方可以看我写的求两线段交点。
# include <stdio.h> # include <math.h> # define EPS 1e-8 struct point { double x,y; }; void Swap(point &a,point &b)//交换两点 { point t; t=a; a=b; b=t; } double Cross(point a,point b,point c)//求ab ac向量的叉积 { return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } double Area(point v[1505],int n)//求多边形的面积 { int i; double ans=0; for(i=1;i<n;i++) ans+=Cross(v[1],v[i],v[i+1]); return ans/2; } void Equation(point p1,point p2,double &a,double &b,double &c) {//求过点p1,p2的直线ax+by+c=0 a=p2.y-p1.y; b=p1.x-p2.x; c=p1.y*p2.x-p1.x*p2.y; } point Intersection(point p1,point p2,double a,double b,double c) {//求直线ax+by+c=0与点p1,p2的交点t double s1,s2; point t; s1=fabs(a*p1.x+b*p1.y+c); s2=fabs(a*p2.x+b*p2.y+c); t.x=(p1.x*s2+p2.x*s1)/(s1+s2); t.y=(p1.y*s2+p2.y*s1)/(s1+s2); return t; } void Cut(double a,double b,double c,point v[1505],int &m) {//直线ax+by+c=0切多边形v int i,t=0; point u[1505]; for(i=1;i<=m;i++) {//如果点v在直线上或在直线的左侧(直线方向是按多边形逆时针方向) if(a*v[i].x+b*v[i].y+c<EPS) u[++t]=v[i]; else { if(a*v[i-1].x+b*v[i-1].y+c<-EPS) u[++t]=Intersection(v[i-1],v[i],a,b,c); if(a*v[i+1].x+b*v[i+1].y+c<-EPS) u[++t]=Intersection(v[i],v[i+1],a,b,c); } } for(i=1;i<=t;i++) v[i]=u[i]; v[0]=v[t]; v[t+1]=v[1]; m=t; } int main() { int i,j,t,n,m; double a,b,c; point v[1505],p[1505]; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=1;i<=n;i++) scanf("%lf%lf",&v[i].x,&v[i].y); if(Area(v,n)<EPS)//如果给的点的顺序是顺时针,就改为逆时针 for(i=1;i<=n/2;i++) Swap(v[i],v[n+1-i]); v[0]=v[n]; v[n+1]=v[1]; m=n; for(i=0;i<=n+1;i++) p[i]=v[i]; for(i=1;i<=n;i++) {//对原图的每一条边按逆时针方向切割一边 Equation(p[i],p[i+1],a,b,c); Cut(a,b,c,v,m); } printf("%.2f\n",Area(v,m)); } return 0; }