题目链接:传送门
分析:
没有什么好说的就是求一个凸包就好了。可以当作模板、
代码如下:
#include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; const double eps = 1e-10; //判断符号,提高精度 int dcmp(double x){ if(fabs(x)<eps) return 0; else return x < 0 ? -1 : 1; } struct Point{ double x, y; Point(double x = 0, double y = 0) : x(x), y(y) { } bool operator < (const Point& a) const{ if(a.x != x) return x < a.x; return y < a.y; } bool operator == (const Point B)const{ return dcmp(x-B.x)==0&&dcmp(y-B.y)==0; } }; typedef Point Vector; Vector operator + (Vector A, Vector B){ return Vector(A.x+B.x, A.y+B.y); } Vector operator - (Point A, Point B){ return Vector(A.x-B.x, A.y-B.y); } Vector operator * (Vector A, double p){ return Vector(A.x*p, A.y*p); } Vector operator / (Vector A, double p){ return Vector(A.x/p, A.y/p); } double Dot(Vector A, Vector B){//向量相乘 return A.x*B.x + A.y*B.y; //a*b*cos(a,b) } double Length(Vector A){ return sqrt(Dot(A, A)); //向量的长度 } double Angle(Vector A, Vector B){ return acos(Dot(A, B) / Length(A) / Length(B)); //向量的角度 } double Cross(Vector A, Vector B){//叉积 return A.x*B.y - A.y*B.x; } /** 向量(x,y) 绕起点逆时针旋转a度。 x' = x*cosa - y*sina y' = x*sina + y*cosa **/ Vector Rotate(Vector A,double a){ return Vector (A.x*cos(a)-A.y*sin(a),A.x*sin(a)+A.y*cos(a)); } double trans(double ang){ return ang/180*acos(-1.0); } //叉积,可以用来判断方向和求面积 double cross(Point a,Point b,Point c){ return (c.x-a.x)*(b.y-a.y) - (b.x-a.x)*(c.y-a.y); } //求多边形的面积 double S(Point p[],int n) { double ans = 0; p[n] = p[0]; for(int i=1; i<n; i++) ans += cross(p[0],p[i],p[i+1]); if(ans < 0) ans = -ans; return ans / 2.0; } /** 求二维凸包Andrew算法,将所有的点按x小到大(x相等,y小到大)排序 删去重复的点,得到一个序列p1,p2...,然后把p1,p2放入凸包中,从p3 开始当新点再前进方向左边时(可以用叉积判断方向)继续,否则,依次 删除最近加入凸包的点,直到新点再左边。 **/ int ConvexHull(Point *p,int n,Point *stack){ sort(p,p+n); n=unique(p,p+n)-p; int m=0; for(int i=0; i<n; i++) {//如果不希望凸包的边上有输入的点则把两个等号去掉 while(m>1&&cross(stack[m-2],p[i],stack[m-1])<=0) m--; stack[m++]=p[i]; } int k=m; for(int i=n-2; i>=0; i--){ while(m>k&&cross(stack[m-2],p[i],stack[m-1])<=0)m--; stack[m++]=p[i]; } if(n>1) m--; return m; } Vector p[2500]; Vector st[2500]; int main() { int t,n; scanf("%d",&t); while(t--){ scanf("%d",&n); double x,y,w,h,a; int num = 0; double tot = 0; for(int i=0; i<n; i++){ scanf("%lf%lf%lf%lf%lf",&x,&y,&w,&h,&a); double ang = -trans(a); Point o = Point(x,y); p[num++] = o + Rotate(Point(-w/2,-h/2),ang); p[num++] = o + Rotate(Point(w/2,-h/2),ang); p[num++] = o + Rotate(Point(-w/2,h/2),ang); p[num++] = o + Rotate(Point(w/2,h/2),ang); tot+=w*h; } int m = ConvexHull(p,num,st); double area = S(st,m); printf("%.1lf %%\n",tot*100/area); } return 0; } /**** 1 4 4 7.5 6 3 0 8 11.5 6 3 0 9.5 6 6 3 90 4.5 3 4.4721 2.2361 26.565 ****/