模板计几最小矩形覆盖(bzoj1185)
Posted xiaobuxie
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板计几最小矩形覆盖(bzoj1185)相关的知识,希望对你有一定的参考价值。
参考hzwer的:http://hzwer.com/5805.html
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1185
题意:给你n个点,求面积最小的矩形使得它覆盖这n个点
矩形一条边是在凸包上的,所以枚举凸包上的边,并且旋转卡壳维护以这条边为底边的最左点,最右点,最上点,然后就可以找到这个矩形了,复杂度O(n)
1 /************************************************************** 2 Problem: 1185 3 User: xiaobuxie 4 Language: C++ 5 Result: Accepted 6 Time:232 ms 7 Memory:2860 kb 8 ****************************************************************/ 9 10 #include<iostream> 11 #include<cstdio> 12 #include<algorithm> 13 #include<cmath> 14 using namespace std; 15 const int N = 5e4+9; 16 #define eps 1e-7 17 struct Point{ 18 double x,y; 19 Point operator - (Point b){ 20 return (Point){ x - b.x,y - b.y}; 21 } 22 Point operator + (Point b){ 23 return (Point){x+b.x,y+b.y}; 24 } 25 Point operator * (double v ){ 26 return (Point){ v * x,v * y}; 27 } 28 }p[N],ch[N],ansp[10],temp[10]; 29 double ans; 30 double cross(Point a,Point b,Point c){ 31 return ( b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y); 32 } 33 double dot( Point a,Point b,Point c){ 34 return (b.x - a.x) * (c.x - a.x) + (b.y - a.y) * (c.y - a.y); 35 } 36 double dis(Point a,Point b){ 37 return sqrt( (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); 38 } 39 bool cmp(Point a,Point b){ 40 if( fabs(a.x - b.x) < eps ) return a.y < b.y - eps; 41 return a.x < b.x ; 42 } 43 int n,m; 44 void Andrew(){ 45 sort(p,p+n,cmp); 46 m = 0; 47 for(int i = 0;i<n;++i){ 48 while( m > 1 && cross( ch[m-2] , p[i],ch[m-1]) > -eps) --m; 49 ch[m++] = p[i]; 50 } 51 int k = m; 52 for(int i = n-2;i>=0;--i){ 53 while( m > k && cross(ch[m-2],p[i],ch[m-1]) > -eps) --m; 54 ch[m++] = p[i]; 55 } 56 if( n > 1) --m; 57 } 58 void RC(){ 59 int l = 1,r = 1,h = 1; 60 ans = 1e60; 61 double L,R,D,H; 62 ch[m] = ch[0]; 63 for(int i = 0;i<m;++i){ 64 D = dis(ch[i],ch[i+1]); 65 while( cross(ch[i],ch[i+1],ch[h+1]) - cross(ch[i],ch[i+1],ch[h]) > -eps) h = (h+1) % m; 66 while( dot(ch[i],ch[i+1],ch[r+1]) - dot(ch[i],ch[i+1],ch[r]) > -eps) r = (r+1) % m; 67 if( i == 0 ) l = r; 68 while( dot(ch[i],ch[i+1],ch[l+1]) - dot(ch[i],ch[i+1],ch[l]) < eps) l = (l+1) % m; 69 L = dot(ch[i],ch[i+1],ch[l]) / D; 70 R = dot(ch[i],ch[i+1],ch[r]) / D; 71 H = cross(ch[i],ch[i+1],ch[h]) / D; 72 if( H < 0 ) H = -H; 73 double S = (R-L) * H; 74 if( S < ans - eps){ 75 ans = S; 76 ansp[0] = ch[i] + (ch[i+1] - ch[i]) * (R/D); 77 ansp[1] = ansp[0] + (ch[r] - ansp[0]) * ( H / dis(ansp[0],ch[r]) ); 78 ansp[2] = ansp[1] - (ansp[0] - ch[i]) * ( (R-L) / dis(ansp[0],ch[i])); 79 ansp[3] = ansp[2] - ( ansp[1] - ansp[0] ); 80 } 81 } 82 } 83 int main(){ 84 scanf("%d",&n); 85 for(int i = 0;i<n;++i) scanf("%lf %lf",&p[i].x,&p[i].y); 86 Andrew(); 87 RC(); 88 printf("%.5f ",ans); 89 int id = 0; 90 for(int i = 1;i<=3;++i){ 91 if( ansp[i].y < ansp[id].y - eps || ( fabs(ansp[i].y - ansp[id].y)<eps && ansp[i].x < ansp[id].x - eps )){ 92 id = i; 93 } 94 } 95 for(int i = 0;i<=3;++i){ 96 printf("%.5f %.5f ",ansp[ (i+id) % 4].x,ansp[ (i + id)%4].y); 97 } 98 return 0; 99 }
以上是关于模板计几最小矩形覆盖(bzoj1185)的主要内容,如果未能解决你的问题,请参考以下文章