这道题是一个简单的凸包问题
关键的一点就是 把每个块的四个顶点都求出来 最后排序求凸包 求的时候涉及到角度旋转 因为计算机上的三角函数都是弧度制的 转换的时候注意一点 自己写的旋转的函数的角度参数是正的 还是负的 也要注意 否者很容易出错
下面看代码 用的是刘汝佳的模版 本人感觉用着不错 比自己写的好多了 计算几何模版需要高度可靠
#include<cstdio>
#include<cmath>
#include<algorithm>
#define eps 1e-8
using namespace std;
struct Point
{
double x,y;
Point (double x = 0,double y = 0):x(x),y(y){}
};
typedef struct Point Vector;
Vector operator +(Vector A,Vector B)
{
return Vector(A.x+B.x,A.y+B.y);
}
Vector operator -(Vector A,Vector B)
{
return Vector(A.x-B.x,A.y-B.y);
}
Vector Rotate(Vector A, double rad)
{
return Vector(A.x*cos(rad) - A.y*sin(rad),A.x*sin(rad) + A.y*cos(rad));
}
double Cross(Vector A, Vector B)
{
return A.x*B.y -A.y*B.x;
}
double PolygonArea(Point *p, int n)
{
double area = 0;
for(int i = 0 ; i < n-1; i++)
area += Cross(p[i] - p[0], p[i+1] - p[0]);
return area / 2;
}
int cmp(Point a,Point b)
{
if(a.x<b.x)return 1;
else if(a.x == b.x && a.y < b.y)return 1;
return 0;
}
int ConvexHull(Point *s,int n,Point *ch)
{
sort(s,s+n,cmp);
int m = 0;
for(int i = 0; i < n; i++)
{
while(m >1 && Cross(ch[m-1]-ch[m-2],s[i]-ch[m-2])<= 0)m--;
ch[m++] = s[i];
}
int k = m;
for(int i = n-2; i >=0; i--)
{
while(m > k && Cross(ch[m-1]-ch[m-2],s[i]-ch[m-2]) <= 0)m--;
ch[m++] = s[i];
}
if(n>1)m--;
return m;
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif // LOCAL
int T;
Point p[2500],ch[2500];
scanf("%d",&T);
while(T--)
{
int n, pc = 0;
double area1 = 0;
scanf("%d",&n);
for(int i = 0; i <n; i++)
{
double x,y,w,h,ang,j;
scanf("%lf%lf%lf%lf%lf",&x,&y,&w,&h,&j);
Point o(x,y);
ang = -j*acos(-1)/180.0;//逆时针的角度
p[pc++] = o + Rotate(Vector(-w/2,-h/2),ang);//因为Rotate函数的ang是逆时针的
p[pc++] = o + Rotate(Vector(w/2,-h/2),ang);
p[pc++] = o + Rotate(Vector(-w/2,h/2),ang);
p[pc++] = o + Rotate(Vector(w/2,h/2),ang);
area1 += w*h;
}
int m = ConvexHull(p,pc,ch);
double area2 = PolygonArea(ch,m);
printf("%.1lf %%\n",area1*100/area2);
}
return 0;
}