這道題是一個簡單的凸包問題
關鍵的一點就是 把每個塊的四個頂點都求出來 最後排序求凸包 求的時候涉及到角度旋轉 因爲計算機上的三角函數都是弧度制的 轉換的時候注意一點 自己寫的旋轉的函數的角度參數是正的 還是負的 也要注意 否者很容易出錯
下面看代碼 用的是劉汝佳的模版 本人感覺用着不錯 比自己寫的好多了 計算幾何模版需要高度可靠
#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;
}