bzoj 1185: [HNOI2007]最小矩形覆盖

%%hzwer,,可以通过蹩脚的画图法发现,矩形的一边会和凸包一边重合。所以就可以枚举边,然后在用旋转卡壳的方法求出左边界,上边界,右边界就是当前的最小面积。

这题细节太神了、、、(应该先做下一题,,,)

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 #define eps 1e-8
 5 using namespace std;
 6 double ans=1e60;
 7 int n,top;
 8 struct point{
 9     double x,y;
10     point(){}
11     point(double _x, double _y):x(_x),y(_y){}
12     friend bool operator < (point a, point b){
13         return fabs(a.y-b.y)<eps?a.x<b.x:a.y<b.y;
14     }
15     friend bool operator == (point a, point b){
16         return fabs(a.x-b.x)<eps && fabs(a.y-b.y)<eps;
17     }
18     friend bool operator != (point a, point b){
19         return !(a==b);
20     }
21     friend point operator + (point a, point b){
22         return point(a.x+b.x,a.y+b.y);
23     }
24     friend point operator - (point a, point b){
25         return point (a.x-b.x,a.y-b.y);
26     }
27     friend point operator * (point a, double b){
28         return point (a.x*b,a.y*b);
29     }
30     friend double operator * (point a, point b){
31         return a.x*b.y-a.y*b.x;
32     }
33     friend double operator / (point a, point b){
34         return a.x*b.x+a.y*b.y;
35     }
36     friend double dis(point a){
37         return sqrt(a.x*a.x+a.y*a.y);
38     }
39 }p[50005],q[50005],t[5];
40 bool cmp(point a, point b)
41 {
42     double t=(a-p[1])*(b-p[1]);
43     if (fabs(t)<eps) return dis(p[1]-a)-dis(p[1]-b)<0;
44     return t>0;
45 }
46 void Graham()
47 {
48     for (int i=2; i<=n; i++)
49         if (p[i]<p[1]) swap(p[1],p[i]);
50     sort(p+2,p+n+1,cmp);
51     q[++top]=p[1]; 
52     for (int i=2; i<=n; i++)
53     {
54         while (top>1 && (q[top]-q[top-1])*(p[i]-q[top])<eps) top--;
55         q[++top]=p[i];
56     } 
57     q[0]=q[top];
58 }
59 void RC()
60 {
61     int l=1,r=1,p=1;
62     double L,R,D,H;
63     for (int i=0; i<top; i++)
64     {
65         D=dis(q[i]-q[i+1]);
66         while ((q[i+1]-q[i])*(q[p+1]-q[i])-(q[i+1]-q[i])*(q[p]-q[i])>-eps) p=(p+1)%top;
67         while ((q[i+1]-q[i])/(q[r+1]-q[i])-(q[i+1]-q[i])/(q[r]-q[i])>-eps) r=(r+1)%top;
68         if (i==0) l=r;
69         while ((q[i+1]-q[i])/(q[l+1]-q[i])-(q[i+1]-q[i])/(q[l]-q[i])<eps) l=(l+1)%top;
70         L=(q[i+1]-q[i])/(q[l]-q[i])/D; 
71         R=(q[i+1]-q[i])/(q[r]-q[i])/D;
72         H=(q[i+1]-q[i])*(q[p]-q[i])/D;
73         double tmp=fabs(H)*(R-L);
74         if (tmp<ans)
75         {
76             ans=tmp;
77             t[0]=q[i]+(q[i+1]-q[i])*(R/D);
78             t[1]=t[0]+(q[r]-t[0])*(H/dis(t[0]-q[r]));
79             t[2]=t[1]-(t[0]-q[i])*((R-L)/dis(q[i]-t[0]));
80             t[3]=t[2]-(t[1]-t[0]);
81         }
82     }
83 }
84 int main()
85 {
86     scanf("%d",&n);
87     for (int i=1; i<=n; i++) scanf("%lf%lf",&p[i].x,&p[i].y);
88     Graham(); RC();
89     printf("%.5lf\n",ans);
90     int fir=0;
91     for (int i=1; i<=3; i++)
92         if (t[i]<t[fir]) fir=i;
93     for (int i=0; i<=3; i++)
94         printf("%.5lf %.5lf\n",t[(i+fir)%4].x,t[(i+fir)%4].y);
95     return 0;
96 }

 

posted @ 2017-03-02 07:19  ws_ccd  阅读(584)  评论(0编辑  收藏  举报