1 条题解

  • 0
    @ 2025-5-4 16:52:42

    本题要计算美术馆中能看到墙壁上每个点的区域面积。

    基本概念与数据结构:定义了点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
    上传者