• 【UVA10652】Board Wrapping(求凸包面积)


    点此看题面

    大致题意: 告诉你若干个矩形的重心坐标相对(y)轴的偏转角度,求矩形面积和能围住这些矩形的最小凸包面积之比。

    矩形面积和

    这应该是比较好求的吧。

    已经给了你长和宽,直接乘起来累加即可。

    最小凸包面积

    这道题关键还是在于求凸包面积。

    首先,我们要注意将题目中给出的角度转换成弧度,还要记得取相反数,不然调死你。

    这段代码可以与旋转函数放在一起:

    inline Point Rotate(Vector A,double deg)
    {
    	register double rad=deg*acos(-1)/180;dcmp(rad)<0&&(rad+=2*acos(-1)),rad=-rad;//将角度转换成弧度,并取相反数
    	return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));//返回旋转后的点的坐标
    } 
    

    则我们就可以很方便地求出每个矩形四个顶点的坐标了。

    枚举四个方向,分别将对应的向量((±frac{s1}2)(±frac{s2}2))进行旋转,然后加上原先点的坐标即可((s1,s2)分别为长和宽)。

    这段代码如下:

    A=Point(x,y),
    P.p[++P.n]=A+Rotate(Point(s1/2,s2/2),deg),
    P.p[++P.n]=A+Rotate(Point(s1/2,-s2/2),deg),
    P.p[++P.n]=A+Rotate(Point(-s1/2,s2/2),deg),
    P.p[++P.n]=A+Rotate(Point(-s1/2,-s2/2),deg);
    

    这样,我们就可以得到(4n)个点,然后将这些点求一个凸包,然后作出凸包面积即可。

    这段过程比较板子,可以参考这篇博客:初学计算几何(四)——初识凸包

    具体实现详见代码吧。

    代码

    #include<bits/stdc++.h>
    #define N 600
    using namespace std;
    int n;
    namespace ComputationGeometry
    {
    	#define eps 1e-10
    	inline int dcmp(double x) {return fabs(x)<eps?0:(x>0?1:-1);}
    	struct Point
    	{
    		double x,y;
    		Point(double nx=0,double ny=0):x(nx),y(ny){}
    	};
    	typedef Point Vector;
    	inline Vector operator + (Point A,Point B) {return Vector(A.x+B.x,A.y+B.y);}
    	inline Vector operator - (Point A,Point B) {return Vector(A.x-B.x,A.y-B.y);}
    	inline Vector operator * (Vector A,double x) {return Vector(A.x*x,A.y*x);}
    	inline Vector operator / (Vector A,double x) {return Vector(A.x/x,A.y/x);}
    	inline bool operator < (Vector A,Vector B) {return fabs(A.x-B.x)>eps?A.x<B.x:A.y<B.y;}
    	inline double Cro(Vector A,Vector B) {return A.x*B.y-A.y*B.x;}
    	inline Point Rotate(Vector A,double deg)//旋转
    	{
    		register double rad=deg*acos(-1)/180;dcmp(rad)<0&&(rad+=2*acos(-1)),rad=-rad;
    		return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
    	} 
    	struct Polygon
    	{
    		int n;Point p[(N<<2)+5];
    		Polygon() {n=0;}
    	};
    	typedef Polygon ConvexHull;
    	inline double PolygonArea(Polygon P)//求多边形(凸包)面积
    	{
    		register int i;register double res=0;
    		for(i=2;i<P.n;++i) res+=Cro(P.p[i]-P.p[1],P.p[i+1]-P.p[1])/2;
    		return res;
    	}
    	inline ConvexHull GetConvexHull(Polygon P)//求凸包
    	{
    		register int i,t;register Polygon S=P;register ConvexHull res;
    		for(sort(S.p+1,S.p+S.n+1),i=1;i<=S.n;++i)
    		{
    			while(res.n>1&&dcmp(Cro(res.p[res.n]-res.p[res.n-1],S.p[i]-res.p[res.n-1]))<=0) --res.n;
    			res.p[++res.n]=S.p[i];
    		}
    		for(t=res.n,i=S.n-1;i;--i)
    		{
    			while(res.n>t&&dcmp(Cro(res.p[res.n]-res.p[res.n-1],S.p[i]-res.p[res.n-1]))<=0) --res.n;
    			res.p[++res.n]=S.p[i];
    		}
    		return res;
    	}
    };
    using namespace ComputationGeometry;
    int main()
    {
    	register int test_tot,i;register double x,y,s1,s2,deg,sum;register Point A;register Polygon P;register ConvexHull H;scanf("%d",&test_tot);
    	while(test_tot--)
    	{
    		for(scanf("%d",&n),P.n=sum=0,i=1;i<=n;++i) 
    		{
    			scanf("%lf%lf%lf%lf%lf",&x,&y,&s1,&s2,&deg),A=Point(x,y),sum+=s1*s2,//同时统计矩形面积和
    			P.p[++P.n]=A+Rotate(Point(s1/2,s2/2),deg),P.p[++P.n]=A+Rotate(Point(s1/2,-s2/2),deg),P.p[++P.n]=A+Rotate(Point(-s1/2,s2/2),deg),P.p[++P.n]=A+Rotate(Point(-s1/2,-s2/2),deg);//存储点
    		}
    		printf("%.1lf %%
    ",100*sum/PolygonArea(GetConvexHull(P)));//计算答案
    	}
    	return 0;
    }
    
  • 相关阅读:
    MySQL执行计划解读(转载)
    排序算法
    Linux下在防火墙中开启80端口、3306端口
    Android APN
    PB之——DropDownListBox 与 DropDownPictureListBox
    CSS总则。
    WIN7系统中设置默认登录用户
    Javascript日期比较
    myeclipse中UTF-8设置
    webview loadUrl() 弹出系统浏览器解决办法
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/UVA10652.html
Copyright © 2020-2023  润新知