码迷,mamicode.com
首页 > 其他好文 > 详细

【模板】【计几】最小矩形覆盖(bzoj1185)

时间:2020-02-04 20:48:33      阅读:76      评论:0      收藏:0      [点我收藏+]

标签:hide   space   closed   using   ++i   面积   eve   use   gif   

参考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\n",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\n",ansp[ (i+id) % 4].x,ansp[ (i + id)%4].y);
97     }
98     return 0;
99 }
View Code

 

【模板】【计几】最小矩形覆盖(bzoj1185)

标签:hide   space   closed   using   ++i   面积   eve   use   gif   

原文地址:https://www.cnblogs.com/xiaobuxie/p/12260631.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!