zoukankan      html  css  js  c++  java
  • bzoj1185 [HNOI2007]最小矩形覆盖 旋转卡壳求凸包

    [HNOI2007]最小矩形覆盖

    Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge
    Submit: 2081  Solved: 920
    [Submit][Status][Discuss]

    Description

    给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形,
    输出所求矩形的面积和四个顶点坐标
     

    Input

    第一行为一个整数n(3<=n<=50000)
    从第2至第n+1行每行有两个浮点数,表示一个顶点的x和y坐标,不用科学计数法
     

    Output

    第一行为一个浮点数,表示所求矩形的面积(精确到小数点后5位),
    接下来4行每行表示一个顶点坐标,要求第一行为y坐标最小的顶点,
    其后按逆时针输出顶点坐标.如果用相同y坐标,先输出最小x坐标的顶点

    Sample Input

    6 1.0 3.00000
    1 4.00000
    2.0000 1
    3 0.0000
    3.00000 6
    6.0 3.0

    Sample Output

    18.00000
    3.00000 0.00000
    6.00000 3.00000
    3.00000 6.00000
    0.00000 3.00000

    HINT

     

    Source

    [Submit][Status][Discuss]


    HOME Back

    首先有一个结论,矩形的一条边一定在凸包上!!!
    枚举凸包上的边
    用旋转卡壳在凸包上找矩形另外三点。。
    差不多吧,其它三个点可以找的吧,而且也是有单调性的。
     1 #pragma GCC optimize(2)
     2 #pragma G++ optimize(2)
     3 #include<cstring>
     4 #include<cmath>
     5 #include<iostream>
     6 #include<algorithm>
     7 #include<cstdio>
     8 
     9 #define eps 0.00000001
    10 #define N 50007
    11 using namespace std;
    12 inline int read()
    13 {
    14     int x=0,f=1;char ch=getchar();
    15     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    16     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    17     return x*f;
    18 }
    19 
    20 int n,tot;
    21 double ans=1e60;
    22 struct P
    23 {
    24     double x,y;
    25     P(){}
    26     P(double _x,double _y):x(_x),y(_y){}
    27     friend bool operator<(P a,P b){return fabs(a.y-b.y)<eps?a.x<b.x:a.y<b.y;}
    28     friend bool operator==(P a,P b){return fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps;}
    29     friend bool operator!=(P a,P b){return !(a==b);}
    30     friend P operator+(P a,P b){return P(a.x+b.x,a.y+b.y);}
    31     friend P operator-(P a,P b){return P(a.x-b.x,a.y-b.y);}
    32     friend double operator*(P a,P b){return a.x*b.y-a.y*b.x;}
    33     friend P operator*(P a,double b){return P(a.x*b,a.y*b);}
    34     friend double operator/(P a,P b){return a.x*b.x+a.y*b.y;}
    35     friend double dis(P a){return sqrt(a.x*a.x+a.y*a.y);}
    36 }p[N],q[N],t[5];
    37 
    38 bool cmp(P a,P b)
    39 {
    40     double t=(a-p[1])*(b-p[1]);
    41     if(fabs(t)<eps)return dis(p[1]-a)-dis(p[1]-b)<0;
    42     return t>0;
    43 }
    44 void Graham()
    45 {
    46     for (int i=2;i<=n;i++)
    47         if(p[i]<p[1])swap(p[i],p[1]);
    48     sort(p+2,p+n+1,cmp);
    49     q[++tot]=p[1];
    50     for (int i=2;i<=n;i++)
    51     {
    52         while(tot>1&&(q[tot]-q[tot-1])*(p[i]-q[tot])<eps)tot--;
    53         q[++tot]=p[i];
    54     }
    55     q[0]=q[tot];//凸包是一个回路。
    56 }
    57 void RC()
    58 {
    59     int l=1,r=1,p=1;
    60     double L,R,D,H;
    61     for (int i=0;i<tot;i++)
    62     {
    63         D=dis(q[i]-q[i+1]);
    64         while((q[i+1]-q[i])*(q[p+1]-q[i])-(q[i+1]-q[i])*(q[p]-q[i])>-eps)p=(p+1)%tot;
    65         while((q[i+1]-q[i])/(q[r+1]-q[i])-(q[i+1]-q[i])/(q[r]-q[i])>-eps)r=(r+1)%tot;
    66         if(i==0)l=r;
    67         while((q[i+1]-q[i])/(q[l+1]-q[i])-(q[i+1]-q[i])/(q[l]-q[i])<eps)l=(l+1)%tot;
    68         L=(q[i+1]-q[i])/(q[l]-q[i])/D,R=(q[i+1]-q[i])/(q[r]-q[i])/D;
    69         H=(q[i+1]-q[i])*(q[p]-q[i])/D;
    70         if(H<0)H=-H;
    71         double tmp=(R-L)*H;
    72         if(tmp<ans)
    73         {
    74             ans=tmp;
    75             t[0]=q[i]+(q[i+1]-q[i])*(R/D);
    76             t[1]=t[0]+(q[r]-t[0])*(H/dis(t[0]-q[r]));
    77             t[2]=t[1]-(t[0]-q[i])*((R-L)/dis(q[i]-t[0]));
    78             t[3]=t[2]-(t[1]-t[0]);
    79         }
    80     }
    81 }
    82 int main()
    83 {
    84     n=read();
    85     for (int i=1;i<=n;i++)
    86         scanf("%lf%lf",&p[i].x,&p[i].y);
    87     Graham();
    88     RC();
    89     printf("%.5lf
    ",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
    ",t[(i+fir)%4].x,t[(i+fir)%4].y);
    95 }
  • 相关阅读:
    博客是一种心情
    双显示器和双鼠标
    C++ Primer Plus 第六版 代码笔记
    Bug,昂首走进2005
    让万能五笔2004免费版改首页的功能见鬼去吧。
    Gmail提供POP3和SMTP已经老长时间了
    快过年回家了,发点实用的东西给大家
    关于博客园Post的时候排版的一点小建议
    在.Net下进行MicroStation(GG)的开发(一)
    验证域的另一方法
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8530629.html
Copyright © 2011-2022 走看看