给定一些长方形的坐标,求长方形的面积与围住这些长方形面积的凸包的百分比.
首先假设长方形都是水平放置,那么根据长和宽还有中心坐标,可以求出四个顶点的坐标,然后求出从中心指向顶点的向量,和角度转化成的弧度,向量旋转之后得到一个新的向量
是由中心指向新的顶点,加上中心点就得到新的顶点的坐标.可以画图理解.
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 const double PI = acos(-1.0); 7 const int maxn=2500; 8 double torad(double deg) {return deg/180*PI;} //角度转化成弧度 9 10 struct Point 11 { 12 double x,y; 13 Point(double x=0,double y=0):x(x),y(y) {} 14 }p[maxn],ch[maxn]; 15 typedef Point Vector; 16 17 Vector operator + (const Vector& A, const Vector& B) { return Vector(A.x+B.x, A.y+B.y); } 18 Vector operator - (const Point& A, const Point& B) { return Vector(A.x-B.x, A.y-B.y); } 19 Vector operator * (const Vector& A, double p) { return Vector(A.x*p, A.y*p); } 20 Vector operator / (const Vector& A, double p) { return Vector(A.x/p, A.y/p); } 21 22 bool operator < (const Point& a, const Point& b) //结构体运算符的重载 23 { 24 return a.x < b.x || (a.x == b.x && a.y < b.y); 25 } 26 27 const double eps = 1e-8; //比较函数 28 int dcmp(double x) { if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; } 29 30 bool operator == (const Point& a, const Point &b) 31 { 32 return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0; 33 } 34 35 //基本运算: 36 double dist(const Vector& A, const Vector& B) {return sqrt(pow(A.x-B.x,2)+pow(A.y-B.y,2));} 37 double Dot(const Vector& A, const Vector& B) { return A.x*B.x + A.y*B.y; } 38 double Length(const Vector& A) { return sqrt(Dot(A, A)); } 39 double Angle(const Vector& A, const Vector& B) { return acos(Dot(A, B) / Length(A) / Length(B)); } 40 double Cross(const Vector& A, const Vector& B) { return A.x*B.y - A.y*B.x; } 41 double Area2(Point A, Point B, Point C) {return Cross(B-A, C-A);} 42 43 //向量旋转 rad是弧度 逆时针为正 44 Vector Rotate(const Vector& A, double rad) 45 { 46 return Vector(A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad)); 47 } 48 49 int main() 50 { 51 //freopen("a.txt","r",stdin); 52 int t,N,n; 53 double a,b,c,d,e; 54 Point s,s1; 55 scanf("%d",&t); 56 while(t--) 57 { 58 scanf("%d",&N); 59 n=0; 60 double area=0,sum=0; 61 for(int i=0;i<N;i++) 62 { 63 scanf("%lf%lf%lf%lf%lf",&s.x,&s.y,&c,&d,&e); 64 sum+=c*d; 65 e=torad(e); //转化成弧度 66 s1=Point(s.x-c/2,s.y-d/2); //得到 四个角的坐标 67 p[n++]=s+Rotate(s1-s,-e); //必须是向量旋转,得到顶点指向中心点的向量,然后旋转,加上 s 得到旋转后的顶点坐标 68 s1=Point(s.x-c/2,s.y+d/2); 69 p[n++]=s+Rotate(s1-s,-e); 70 s1=Point(s.x+c/2,s.y+d/2); 71 p[n++]=s+Rotate(s1-s,-e); 72 s1=Point(s.x+c/2,s.y-d/2); 73 p[n++]=s+Rotate(s1-s,-e); 74 } 75 sort(p,p+n); //排序 后 求凸包 76 int m=0; 77 for(int i=0;i<n;i++) 78 { 79 while(m>1&&dcmp(Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]))<=0) m--; 80 ch[m++]=p[i]; 81 } 82 int k=m; 83 for(int i=n-2;i>=0;i--) 84 { 85 while(m>k&&dcmp(Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]))<=0) m--; 86 ch[m++]=p[i]; 87 } 88 for(int i=1;i<m-1;i++) //求凸包面积 (这里是两倍) 89 { 90 area+=Cross(ch[i]-ch[0],ch[i+1]-ch[0]); 91 } 92 area/=2; 93 area=sum/area*100; //得到 木板占凸包的 百分比 94 printf("%.1lf %% ",area); 95 } 96 return 0; 97 }