<题目链接>
题目大意:
按顺时针顺序给出一个N边形,求N边形的核的面积。
(多边形的核:它是平面简单多边形的核是该多边形内部的一个点集该点集中任意一点与多边形边界上一点的连线都处于这个多边形内部。)
#include <cstdio> #include <cmath> #include <iostream> using namespace std; #define eps 1e-8 const int MAXN=10017; int n; double r; int cCnt,curCnt; struct point { double x,y; point(double a=0,double b=0):x(a),y(b){} }; point points[MAXN],p[MAXN],q[MAXN]; point operator - (point A,point B) { return point(A.x-B.x,A.y-B.y); } double Cross(point A,point B){ return A.x*B.y-A.y*B.x; } void getline(point x,point y,double &a,double &b,double &c) //得到直线的方程系数 { a = y.y - x.y; b = x.x - y.x; c = y.x * x.y - x.x * y.y; } void initial() //初始化放置多边形顶点的p数组 { for(int i = 1; i <= n; i++)p[i] = points[i]; p[n+1] = p[1]; p[0] = p[n]; cCnt = n; } point intersect(point x,point y,double a,double b,double c) //求点x、y形成的直线与已知直线a、b、c、的交点 { double u = fabs(a * x.x + b * x.y + c); double v = fabs(a * y.x + b * y.y + c); point pt; pt.x=(x.x * v + y.x * u) / (u + v); pt.y=(x.y * v + y.y * u) / (u + v); return pt; } void cut(double a,double b ,double c) { curCnt = 0; int i; for(i = 1; i <= cCnt; ++i) { if(a*p[i].x + b*p[i].y + c >= 0)q[++curCnt] = p[i]; // c因为精度问题,可能会偏小。所以有些点本应在右側而没在。 else { if(a*p[i-1].x + b*p[i-1].y + c > 0) { q[++curCnt] = intersect(p[i],p[i-1],a,b,c); } if(a*p[i+1].x + b*p[i+1].y + c > 0) //原理同上 { q[++curCnt] = intersect(p[i],p[i+1],a,b,c); } } } for(i = 1; i <= curCnt; ++i)p[i] = q[i]; p[curCnt+1] = q[1]; p[0] = p[curCnt]; cCnt = curCnt; } void solve() { initial(); for(int i = 1; i <= n; ++i) { double a,b,c; getline(points[i],points[i+1],a,b,c); cut(a,b,c); //用原多边形的边界去切割p数组表示的内核多边形 } } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i = 1; i <= n; i++) { scanf("%lf%lf",&points[i].x,&points[i].y); } points[n+1] = points[1]; solve(); if(cCnt<=2) //如果1或者两个点,直接输出面积为0.00 printf("%.2lf ",0); else { double area=0; //利用叉乘算出多边形的面积 for(int i=1;i<cCnt;i++) { area+=Cross(p[i]-p[1],p[i+1]-p[1]); } printf("%.2lf ",fabs(area)/2.0); } } return 0; }
2018-08-03