题意:小度熊有一个桌面,小度熊剪了很多矩形放在桌面上,小度熊想知道能把这些矩形包围起来的面积最小的矩形的面积是多少。
求个凸包,矩形的边一定在凸包上,枚举边,求最大值,即为所求,多年不拍几何,直接套了个模板
以后还得练练
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 typedef double typev; 10 const double eps = 1e-8; 11 const int N = 4055; 12 int sign(double d){ 13 return d < -eps ? -1 : (d > eps); 14 } 15 struct point{ 16 typev x, y; 17 void in() 18 { 19 scanf("%lf%lf",&x,&y); 20 } 21 point operator-(point d){ 22 point dd; 23 dd.x = this->x - d.x; 24 dd.y = this->y - d.y; 25 return dd; 26 } 27 point operator+(point d){ 28 point dd; 29 dd.x = this->x + d.x; 30 dd.y = this->y + d.y; 31 return dd; 32 } 33 void read(){ scanf("%lf%lf", &x, &y); } 34 }ps[N],pd[N]; 35 int n, cn; 36 double dist(point d1, point d2){ 37 return sqrt(pow(d1.x - d2.x, 2.0) + pow(d1.y - d2.y, 2.0)); 38 } 39 double dist2(point d1, point d2){ 40 return pow(d1.x - d2.x, 2.0) + pow(d1.y - d2.y, 2.0); 41 } 42 bool cmp(point d1, point d2){ 43 return d1.y < d2.y || (d1.y == d2.y && d1.x < d2.x); 44 } 45 //st1-->ed1叉乘st2-->ed2的值 46 typev xmul(point st1, point ed1, point st2, point ed2){ 47 return (ed1.x - st1.x) * (ed2.y - st2.y) - (ed1.y - st1.y) * (ed2.x - st2.x); 48 } 49 typev dmul(point st1, point ed1, point st2, point ed2){ 50 return (ed1.x - st1.x) * (ed2.x - st2.x) + (ed1.y - st1.y) * (ed2.y - st2.y); 51 } 52 //多边形类 53 struct poly{ 54 static const int N = 4005; //点数的最大值 55 point ps[N+5]; //逆时针存储多边形的点,[0,pn-1]存储点 56 int pn; //点数 57 poly() { pn = 0; } 58 //加进一个点 59 void push(point tp){ 60 ps[pn++] = tp; 61 } 62 //第k个位置 63 int trim(int k){ 64 return (k+pn)%pn; 65 } 66 void clear(){ pn = 0; } 67 }; 68 //返回含有n个点的点集ps的凸包 69 poly graham(point* ps, int n){ 70 sort(ps, ps + n, cmp); 71 poly ans; 72 if(n <= 2){ 73 for(int i = 0; i < n; i++){ 74 ans.push(ps[i]); 75 } 76 return ans; 77 } 78 ans.push(ps[0]); 79 ans.push(ps[1]); 80 point* tps = ans.ps; 81 int top = -1; 82 tps[++top] = ps[0]; 83 tps[++top] = ps[1]; 84 for(int i = 2; i < n; i++){ 85 while(top > 0 && xmul(tps[top - 1], tps[top], tps[top - 1], ps[i]) <= 0) top--; 86 tps[++top] = ps[i]; 87 } 88 int tmp = top; //注意要赋值给tmp! 89 for(int i = n - 2; i >= 0; i--){ 90 while(top > tmp && xmul(tps[top - 1], tps[top], tps[top - 1], ps[i]) <= 0) top--; 91 tps[++top] = ps[i]; 92 } 93 ans.pn = top; 94 return ans; 95 } 96 //求点p到st->ed的垂足,列参数方程 97 point getRoot(point p, point st, point ed){ 98 point ans; 99 double u=((ed.x-st.x)*(ed.x-st.x)+(ed.y-st.y)*(ed.y-st.y)); 100 u = ((ed.x-st.x)*(ed.x-p.x)+(ed.y-st.y)*(ed.y-p.y))/u; 101 ans.x = u*st.x+(1-u)*ed.x; 102 ans.y = u*st.y+(1-u)*ed.y; 103 return ans; 104 } 105 //next为直线(st,ed)上的点,返回next沿(st,ed)右手垂直方向延伸l之后的点 106 point change(point st, point ed, point next, double l){ 107 point dd; 108 dd.x = -(ed - st).y; 109 dd.y = (ed - st).x; 110 double len = sqrt(dd.x * dd.x + dd.y * dd.y); 111 dd.x /= len, dd.y /= len; 112 dd.x *= l, dd.y *= l; 113 dd = dd + next; 114 return dd; 115 } 116 //求含n个点的点集ps的最小面积矩形,并把结果放在ds(ds为一个长度是4的数组即可,ds中的点是逆时针的)中,并返回这个最小面积。 117 double getMinAreaRect(point* ps, int n, point* ds){ 118 int cn, i; 119 double ans; 120 point* con; 121 poly tpoly = graham(ps, n); 122 con = tpoly.ps; 123 cn = tpoly.pn; 124 if(cn <= 2){ 125 ds[0] = con[0]; ds[1] = con[1]; 126 ds[2] = con[1]; ds[3] = con[0]; 127 ans=0; 128 }else{ 129 int l, r, u; 130 double tmp, len; 131 con[cn] = con[0]; 132 ans = 1e40; 133 l = i = 0; 134 while(dmul(con[i], con[i+1], con[i], con[l]) 135 >= dmul(con[i], con[i+1], con[i], con[(l-1+cn)%cn])){ 136 l = (l-1+cn)%cn; 137 } 138 for(r=u=i = 0; i < cn; i++){ 139 while(xmul(con[i], con[i+1], con[i], con[u]) 140 <= xmul(con[i], con[i+1], con[i], con[(u+1)%cn])){ 141 u = (u+1)%cn; 142 } 143 while(dmul(con[i], con[i+1], con[i], con[r]) 144 <= dmul(con[i], con[i+1], con[i], con[(r+1)%cn])){ 145 r = (r+1)%cn; 146 } 147 while(dmul(con[i], con[i+1], con[i], con[l]) 148 >= dmul(con[i], con[i+1], con[i], con[(l+1)%cn])){ 149 l = (l+1)%cn; 150 } 151 tmp = dmul(con[i], con[i+1], con[i], con[r]) - dmul(con[i], con[i+1], con[i], con[l]); 152 tmp *= xmul(con[i], con[i+1], con[i], con[u]); 153 tmp /= dist2(con[i], con[i+1]); 154 len = xmul(con[i], con[i+1], con[i], con[u])/dist(con[i], con[i+1]); 155 if(sign(tmp - ans) < 0){ 156 ans = tmp; 157 ds[0] = getRoot(con[l], con[i], con[i+1]); 158 ds[1] = getRoot(con[r], con[i+1], con[i]); 159 ds[2] = change(con[i], con[i+1], ds[1], len); 160 ds[3] = change(con[i], con[i+1], ds[0], len); 161 } 162 } 163 } 164 return ans+eps; 165 } 166 int main() 167 { 168 int i,j,k; 169 #ifndef ONLINE_JUDGE 170 freopen("1.in","r",stdin); 171 #endif 172 int tt; 173 scanf("%d",&tt); 174 int ca=1; 175 while(tt--) 176 { 177 printf("Case #%d: ",ca++); 178 scanf("%d",&n); 179 for(i=0;i<4*n;i++) 180 { 181 ps[i].in(); 182 } 183 double q=getMinAreaRect(ps,4*n,pd); 184 printf("%d ",int(q+0.5)); 185 } 186 }