• [HNOI2007]最小矩形覆盖


    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    6 
    1.0 3.00000 1 4.00000 2.0000 1 3 0.0000 3.00000 6 6.0 3.0
    输出样例#1: 复制
    18.00000
    3.00000 0.00000
    6.00000 3.00000
    3.00000 6.00000
    0.00000 3.00000
    最小的覆盖矩形肯定有边在凸包上
    先求出凸包,然后枚举凸包上的边为直线构造矩形
    用单调栈求出离该直线最远的点,左边最远的点和右边最远的点
    就可以算出矩形的四个点
    有可能输出-0.0000,所以要特判
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 using namespace std;
      7 typedef long double ld;
      8 struct point
      9 {
     10   ld x,y;
     11 }p[50005],s[50005];
     12 point ansp[5];
     13 ld eps=1e-10,res,ans;
     14 int n,top;
     15 ld cross(point a,point b)
     16 {
     17   return a.x*b.y-b.x*a.y;
     18 }
     19 point operator *(point a,double b)
     20 {
     21   return (point){a.x*b,a.y*b};
     22 }
     23 point operator -(point a,point b)
     24 {
     25   return (point){a.x-b.x,a.y-b.y};
     26 }
     27 point operator +(point a,point b)
     28 {
     29   return (point){a.x+b.x,a.y+b.y};
     30 }
     31 ld dot(point a,point b)
     32 {
     33   return a.x*b.x+a.y*b.y;
     34 }
     35 ld dist(point a)
     36 {
     37   return sqrt(a.x*a.x+a.y*a.y);
     38 }
     39 int dcmp(ld x)
     40 {
     41   if (x<-eps) return -1;
     42   if (x>eps) return 1;
     43   return 0;
     44 }
     45 bool cmp(point a,point b)
     46 {
     47   return (a.y<b.y)||(a.y==b.y&&a.x<b.x);
     48 }
     49 bool cmp2(point a,point b)
     50 {
     51   int t=dcmp(cross((p[1]-a),(p[1]-b)));
     52   if (t==0) return dist(p[1]-a)<dist(p[1]-b);
     53   return t>0;
     54 }
     55 bool cmp3(point a,point b)
     56 {
     57   return atan2(a.y-ansp[1].y,a.x-ansp[1].x)<atan2(b.y-ansp[1].y,b.x-ansp[1].x);
     58 }
     59 void graham()
     60 {int i;
     61   sort(p+1,p+n+1,cmp);
     62   sort(p+2,p+n+1,cmp2);
     63   s[++top]=p[1];s[++top]=p[2];
     64   for (i=3;i<=n;i++)
     65     {
     66       while (top>1&&dcmp(cross((p[i]-s[top-1]),(s[top]-s[top-1])))>=0) top--;
     67       s[++top]=p[i];
     68     }
     69 }
     70 void solve()
     71 {int i;
     72   int pos=2,r=2,l;
     73   s[top+1]=s[1];
     74   for (i=1;i<=top;i++)
     75     {
     76       ld D=dist(s[i+1]-s[i]);
     77       while (dcmp(cross((s[i+1]-s[i]),(s[pos+1]-s[i]))-cross((s[i+1]-s[i]),(s[pos]-s[i])))>0) pos=pos%top+1;
     78       while (dcmp(dot(s[i+1]-s[i],s[r+1]-s[i])-dot(s[i+1]-s[i],s[r]-s[i]))>=0) r=r%top+1;
     79       if (i==1) l=r;
     80       while (dcmp(dot(s[i+1]-s[i],s[l+1]-s[i])-dot(s[i+1]-s[i],s[l]-s[i]))<=0) l=l%top+1;
     81       ld L=dot(s[l]-s[i],s[i+1]-s[i])/D;
     82       ld R=dot(s[i+1]-s[i],s[r]-s[i])/D;
     83       ld H=cross((s[i+1]-s[i]),(s[pos]-s[i]))/D;
     84       res=(R-L)*H;if (res<0) res=-res;
     85       if (dcmp(res-ans)<0)
     86     {
     87       ans=res;
     88       ansp[1]=s[i]+(s[i+1]-s[i])*(L/D);
     89       ansp[2]=s[i]+(s[i+1]-s[i])*(R/D);
     90       ansp[3]=ansp[1]+(s[l]-ansp[1])*(H/dist(s[l]-ansp[1]));
     91       ansp[4]=ansp[2]+(s[r]-ansp[2])*(H/dist(s[r]-ansp[2]));
     92       if (dcmp(ansp[1].x)==0) ansp[1].x=fabs(ansp[1].x);
     93       if (dcmp(ansp[1].y)==0) ansp[1].y=fabs(ansp[1].y);
     94       if (dcmp(ansp[2].x)==0) ansp[2].x=fabs(ansp[2].x);
     95       if (dcmp(ansp[2].y)==0) ansp[2].y=fabs(ansp[2].y);
     96       if (dcmp(ansp[3].x)==0) ansp[3].x=fabs(ansp[3].x);
     97       if (dcmp(ansp[3].y)==0) ansp[3].y=fabs(ansp[3].y);
     98       if (dcmp(ansp[4].x)==0) ansp[4].x=fabs(ansp[4].x);
     99       if (dcmp(ansp[4].y)==0) ansp[4].y=fabs(ansp[4].y);
    100     }
    101     }
    102 }
    103 int main()
    104 {int i;
    105   cin>>n;
    106   ans=2e9;
    107   for (i=1;i<=n;i++)
    108     {
    109       scanf("%Lf%Lf",&p[i].x,&p[i].y);
    110     }
    111   graham();
    112   solve();
    113   printf("%.5Lf
    ",ans);
    114   sort(ansp+1,ansp+5,cmp);
    115   sort(ansp+2,ansp+5,cmp3);
    116   for (i=1;i<=4;i++)
    117     printf("%.5Lf %.5Lf
    ",ansp[i].x,ansp[i].y);
    118 }
  • 相关阅读:
    广义表的创建和遍历
    dev c++ Boost库的安装
    NAT模式
    vmware桥接模式
    smb与samba
    利用Linux的Samba服务模拟NT域
    使用samba进行共享文件操作步骤
    安装chrome
    使用虚拟机上网第二步
    TCP协议三次握手过程分析
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8274587.html
Copyright © 2020-2023  润新知