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

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1185

    题意:

      给出二维平面上的n个点,问你将所有点覆盖的最小矩形面积。

    题解:

      先找出凸包,然后旋转卡壳。

      在旋转卡壳中有一个结论:最小覆盖矩形一定有一条边在凸包上。

      所以先枚举矩形在凸包上的那条边(p[i],p[i+1]),然后利用单调性找出p[i]的对踵点p[u]。

      至于左右两侧的切点p[l]和p[r],要利用它们连线在直线(p[i],p[i+1])上投影长度的单调性求出。

      最后将找出的矩形顶点再做一遍极角排序即可。

    AC Code:

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <math.h>
      5 #include <algorithm>
      6 #define MAX_N 50005
      7 #define INF_LF 1e14
      8 #define EPS 1e-7
      9 
     10 using namespace std;
     11 
     12 struct Coor
     13 {
     14     double x,y;
     15     Coor(double _x,double _y) { x=_x,y=_y; }
     16     Coor(){}
     17     friend Coor operator + (const Coor &a,const Coor &b)
     18     {
     19         return Coor(a.x+b.x,a.y+b.y);
     20     }
     21     friend Coor operator - (const Coor &a,const Coor &b)
     22     {
     23         return Coor(a.x-b.x,a.y-b.y);
     24     }
     25     friend Coor operator * (const Coor &a,double b)
     26     {
     27         return Coor(a.x*b,a.y*b);
     28     }
     29     friend Coor operator / (const Coor &a,double b)
     30     {
     31         return Coor(a.x/b,a.y/b);
     32     }
     33     friend double len(const Coor &a,const Coor &b)
     34     {
     35         return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
     36     }
     37     friend double dot(const Coor &a,const Coor &b)
     38     {
     39         return a.x*b.x+a.y*b.y;
     40     }
     41     friend double cross(const Coor &a,const Coor &b)
     42     {
     43         return a.x*b.y-a.y*b.x;
     44     }
     45     friend double area(const Coor &a,const Coor &b,const Coor &c)
     46     {
     47         return fabs(cross(b-a,c-a));
     48     }
     49     friend double length(const Coor &a)
     50     {
     51         return sqrt(dot(a,a));
     52     }
     53     friend double pro(const Coor &a,const Coor &b)
     54     {
     55         return dot(a,b)/length(b);
     56     }
     57     friend Coor proc(const Coor &a,const Coor &b,const Coor &c)
     58     {
     59         Coor v=c-b;
     60         return b+v*dot(v,a-b)/dot(v,v);
     61     }
     62 };
     63 
     64 int n,tot=0;
     65 double ans=INF_LF;
     66 Coor p[MAX_N];
     67 Coor con[MAX_N];
     68 Coor rect[MAX_N];
     69 
     70 void read()
     71 {
     72     scanf("%d",&n);
     73     for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
     74 }
     75 
     76 bool cmp(const Coor &a,const Coor &b)
     77 {
     78     double c=cross(a-p[1],b-p[1]);
     79     return c!=0 ? c>0 : len(p[1],a)<len(p[1],b);
     80 }
     81 
     82 inline bool eq(double x,double y)
     83 {
     84     return fabs(x-y)<EPS;
     85 }
     86 
     87 void graham()
     88 {
     89     for(int i=2;i<=n;i++)
     90     {
     91         if(p[i].y<p[1].y || (p[i].y==p[1].y && p[i].x<p[1].x))
     92         {
     93             swap(p[i],p[1]);
     94         }
     95     }
     96     sort(p+2,p+1+n,cmp);
     97     con[++tot]=p[1],con[++tot]=p[2];
     98     for(int i=3;i<=n;i++)
     99     {
    100         while(tot>=2 && cross(con[tot]-con[tot-1],p[i]-con[tot])<=0) tot--;
    101         con[++tot]=p[i];
    102     }
    103 }
    104 
    105 inline int mod(int x)
    106 {
    107     return ((x-1)%tot+tot)%tot+1;
    108 }
    109 
    110 void rc()
    111 {
    112     int u=2,l=1,r=1;
    113     for(int i=2;i<=tot;i++)
    114     {
    115         if(con[i].x<con[l].x || (con[i].x==con[l].x && con[i].y>con[l].y)) l=i;
    116         if(con[i].x>con[r].x || (con[i].x==con[r].x && con[i].y<con[r].y)) r=i;
    117     }
    118     for(int i=1;i<=tot;i++)
    119     {
    120         while(area(con[i],con[mod(i+1)],con[u])<area(con[i],con[mod(i+1)],con[mod(u+1)])) u=mod(u+1);
    121         while(pro(con[r]-con[l],con[mod(i+1)]-con[i])<pro(con[r]-con[mod(l+1)],con[mod(i+1)]-con[i])) l=mod(l+1);
    122         while(pro(con[r]-con[l],con[mod(i+1)]-con[i])<pro(con[mod(r+1)]-con[l],con[mod(i+1)]-con[i])) r=mod(r+1);
    123         double w=pro(con[r]-con[l],con[mod(i+1)]-con[i]);
    124         double h=area(con[i],con[mod(i+1)],con[u])/length(con[mod(i+1)]-con[i]);
    125         if(w*h<ans)
    126         {
    127             ans=w*h;
    128             Coor v=con[mod(i+1)]-con[i];
    129             rect[0]=proc(con[l],con[i],con[mod(i+1)]);
    130             rect[1]=proc(con[r],con[i],con[mod(i+1)]);
    131             rect[2]=proc(con[l],con[u],con[u]+v);
    132             rect[3]=proc(con[r],con[u],con[u]+v);
    133         }
    134     }
    135     for(int i=1;i<4;i++)
    136     {
    137         if(rect[i].y<rect[0].y || (rect[i].y==rect[0].y && rect[i].x<rect[0].x))
    138         {
    139             swap(rect[0],rect[i]);
    140         }
    141     }
    142     sort(rect+1,rect+4,cmp);
    143     for(int i=0;i<4;i++)
    144     {
    145         if(eq(rect[i].x,0)) rect[i].x=0;
    146         if(eq(rect[i].y,0)) rect[i].y=0;
    147     }
    148 }
    149 
    150 void work()
    151 {
    152     graham();
    153     rc();
    154     printf("%.5f
    ",ans);
    155     for(int i=0;i<4;i++) printf("%.5f %.5f
    ",rect[i].x,rect[i].y);
    156 }
    157 
    158 int main()
    159 {
    160     read();
    161     work();
    162 }
  • 相关阅读:
    U132973 双生独白
    Remmarguts' Date(A* 短路)
    P3908 数列之异或
    P1469 找筷子
    P1759 通天之潜水
    P2356 弹珠游戏
    P7072 直播获奖
    P7074 方格取数
    CSP2020二轮游记
    P6205 [USACO06JAN]Dollar Dayz S
  • 原文地址:https://www.cnblogs.com/Leohh/p/8969947.html
Copyright © 2011-2022 走看看