1 条题解
-
0
本题要计算美术馆中能看到墙壁上每个点的区域面积。
基本概念与数据结构:定义了点point结构体,包含横纵坐标,以及相关运算如向量减法、求向量模长;定义多边形polygon_convex结构体用向量存储顶点;定义半平面halfplane结构体,通过直线方程ax + by + c <= 0表示。还定义了向量点积dot、叉积det运算,以及判断浮点数正负的sgn函数。 核心算法: core函数用于求多边形核(即能看到多边形所有边的区域) 。先初始化一个包含四个顶点(代表无穷大边界)的多边形res,然后遍历输入多边形的每条边,将其转化为半平面,通过cut函数不断切割res,最终得到多边形核。 cut函数实现多边形与半平面的切割操作。遍历多边形的顶点,判断顶点与半平面的位置关系,在半平面内的顶点直接加入结果多边形;若顶点不在半平面内,则判断其前后相邻顶点与半平面的位置关系,若相邻顶点在半平面内,则计算交点并加入结果多边形。 Intersect函数通过相似三角形原理计算两条直线(一条是多边形的边,一条是半平面边界)的交点。 area函数利用叉积计算多边形面积,通过遍历多边形顶点,累加相邻顶点构成向量的叉积,最后取绝对值除以 2 得到面积。 解题流程:在main函数中,先读取测试用例数t,对于每个测试用例,通过prework函数读取多边形顶点坐标,然后调用mainwork函数,在其中计算多边形核并求其面积,最后通过print函数输出结果。
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #define maxl 1010 #define eps 1e-8 using namespace std; inline int sgn(double x) { if(x>-eps && x<eps) return 0; if(x>0) return 1; else return -1; } struct point { double x,y; point(double a=0,double b=0) { x=a,y=b; } point operator - (const point &b)const { return point(x-b.x,y-b.y); } inline double norm() { return sqrt(x*x+y*y); } }; inline double dot(const point &a,const point &b) { return a.x*b.x+a.y*b.y; } inline double det(const point &a,const point &b) { return a.x*b.y-a.y*b.x; } struct polygon_convex { vector<point> P; polygon_convex(int Size=0) { P.resize(Size); } }; struct halfplane { double a,b,c;//ax+by+c<=0 halfplane(point p=point(),point q=point()) { a=p.y-q.y; b=q.x-p.x; c=det(p,q); } halfplane(double aa=0,double bb=0,double cc=0) { a=aa;b=bb;c=cc; } }; inline double calc(halfplane &L,point &a) { return a.x*L.a+a.y*L.b+L.c; } point Intersect(point &a,point &b,halfplane &L) {//use similar triangles ,line ans halfplaneline point res; double t1=calc(L,a),t2=calc(L,b); res.x=(t2*a.x-t1*b.x)/(t2-t1); res.y=(t2*a.y-t1*b.y)/(t2-t1); return res; } polygon_convex cut(polygon_convex &a,halfplane &L) { int n=a.P.size(); polygon_convex res; for(int i=0;i<n;i++) { if(sgn(calc(L,a.P[i]))<0) res.P.push_back(a.P[i]); else { int j=i-1; if(j<0) j=n-1; if(sgn(calc(L,a.P[j]))<0) res.P.push_back(Intersect(a.P[j],a.P[i],L)); j=i+1; if(j==n) j=0; if(sgn(calc(L,a.P[j]))<0) res.P.push_back(Intersect(a.P[i],a.P[j],L)); } } return res; } const double inf=1e9; polygon_convex core(vector<point> &a) { polygon_convex res; res.P.push_back(point(-inf,-inf)); res.P.push_back(point(inf,-inf)); res.P.push_back(point(inf,inf)); res.P.push_back(point(-inf,inf)); int n=a.size(); for(int i=0;i<n;i++) { halfplane L(a[i],a[(i+1)%n]); res=cut(res,L); } return res; } int n; vector <point> a; double ans; inline void prework() { scanf("%d",&n); a.resize(n); for(int i=0;i<n;i++) scanf("%lf%lf",&a[i].x,&a[i].y); } inline double area(vector<point> &a) { double sum=0;int n=a.size(); for(int i=0;i<n;i++) sum+=det(a[(i+1)%n],a[i]); return fabs(sum/2); } inline void mainwork() { polygon_convex cr=core(a); ans=area(cr.P); } inline void print() { printf("%.2f\n",ans); } int main() { int t; scanf("%d",&t); for(int i=1;i<=t;i++) { prework(); mainwork(); print(); } return 0; }
- 1
信息
- ID
- 280
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 5
- 已通过
- 1
- 上传者