UVA - 10652 Board Wrapping (凸包)
给你n个矩形,求出这些矩形的面积之和与包住所有矩形的最小凸多边形面积的比值。
要开计算几何的坑了,先来道凸包的模板题。
把所有矩形的端点扒出来,求出凸包,直接计算两部分的面积即可。
注意:
1.矩形旋转的角度是顺时针的,进行坐标旋转的时候可能需要取相反数。
2.矩形的端点可能有重复的,在求凸包之前需要去重。
求凸包我用的是把下凸壳和上凸壳拼凑起来的方法,速度较快,而且一些需要用到特殊数据结构的dp问题比如斜率优化都需要用到这样的算法,感觉比较实用。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef double db; 5 const int N=3000+5,inf=0x3f3f3f3f; 6 const db pi=acos(-1); 7 struct P { 8 db x,y; 9 P operator-(P b) {return {x-b.x,y-b.y};} 10 P operator+(P b) {return {x+b.x,y+b.y};} 11 bool operator<(const P& b)const {return x!=b.x?x<b.x:y<b.y;} 12 bool operator==(const P& b)const {return x==b.x&&y==b.y;} 13 db len() {return hypot(x,y);} 14 } p[N],ch[N]; 15 db cross(P a,P b) {return a.x*b.y-a.y*b.x;} 16 db dot(P a,P b) {return a.x*b.x+a.y*b.y;} 17 P rot(P a,db rad) {return {a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad)};} 18 P rot(P a,db rad,P b) {return b+rot(a-b,rad);} 19 20 int nch,n,m,ka; 21 db L; 22 struct Rect {db x,y,w,h,rad;} rect[N]; 23 24 void CH() { 25 sort(p,p+n); 26 n=unique(p,p+n)-p; 27 nch=0; 28 for(int i=0; i<n; ++i) { 29 for(; nch>1&&cross(ch[nch-1]-ch[nch-2],p[i]-ch[nch-2])<=0; --nch); 30 ch[nch++]=p[i]; 31 } 32 int k=nch; 33 for(int i=n-2; i>=0; --i) { 34 for(; nch>k&&cross(ch[nch-1]-ch[nch-2],p[i]-ch[nch-2])<=0; --nch); 35 ch[nch++]=p[i]; 36 } 37 } 38 39 db area() { 40 db ret=0; 41 for(int i=1; i<nch-2; ++i)ret+=cross(ch[i]-ch[0],ch[i+1]-ch[0]); 42 return ret/2; 43 } 44 45 db solve() { 46 db S1=0,S2; 47 for(int i=0; i<n; ++i)S1+=rect[i].w*rect[i].h; 48 CH(); 49 S2=area(); 50 return S1/S2*100; 51 } 52 53 int main() { 54 int T; 55 for(scanf("%d",&T); T--;) { 56 scanf("%d",&m); 57 for(int i=0; i<m; ++i) { 58 scanf("%lf%lf%lf%lf%lf",&rect[i].x,&rect[i].y,&rect[i].w,&rect[i].h,&rect[i].rad); 59 rect[i].rad*=pi/180; 60 } 61 n=0; 62 for(int i=0; i<m; ++i) { 63 p[n++]= {rect[i].x-rect[i].w/2,rect[i].y-rect[i].h/2}; 64 p[n++]= {rect[i].x+rect[i].w/2,rect[i].y-rect[i].h/2}; 65 p[n++]= {rect[i].x-rect[i].w/2,rect[i].y+rect[i].h/2}; 66 p[n++]= {rect[i].x+rect[i].w/2,rect[i].y+rect[i].h/2}; 67 for(int j=n-4; j<n; ++j)p[j]=rot(p[j],-rect[i].rad, {rect[i].x,rect[i].y}); 68 } 69 printf("%.1f %%\n",solve()); 70 } 71 return 0; 72 }