zoukankan      html  css  js  c++  java
  • bzoj 1185 旋转卡壳 最小矩形覆盖

    题目大意 就是求一个最小矩形覆盖,逆时针输出其上面的点

    这里可以看出,那个最小的矩形覆盖必然有一条边经过其中凸包上的两个点,另外三条边必然至少经过其中一个点,而这样的每一个点逆时针走一遍都满足单调性

    所以可以利用旋转卡壳的思想找到这样的三个点

    以每一条边作为基础,循环n次得到n个这样的矩形,找到其中面积最小的即可

    然后自己画画图,作出矩形对应的两条边的单位向量,那么这四个点就非常好求了

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <algorithm>
      6 using namespace std;
      7 #define N 50010
      8 #define eps 1e-9
      9 const double PI = acos(-1.0);
     10 int n , top;
     11 
     12 int dcmp(double x)
     13 {
     14     if(fabs(x)<eps) return 0;
     15     return x<0?-1:1;
     16 }
     17 
     18 struct Point{
     19     double x , y;
     20     Point(double x=0 , double y=0):x(x),y(y){}
     21     void input(){scanf("%lf%lf" , &x , &y);}
     22     void output(){printf("%.5f %.5f
    " , x , y);}
     23     bool operator<(const Point &m)const{
     24         return x<m.x||(x==m.x&&y<m.y);
     25     }
     26 }po[N] , rec[N] , p[4];
     27 
     28 typedef Point Vector;
     29 
     30 Vector operator+(Vector a , Vector b){return Vector(a.x+b.x , a.y+b.y);}
     31 Vector operator-(Vector a , Vector b){return Vector(a.x-b.x , a.y-b.y);}
     32 Vector operator*(Vector a , double b){return Vector(a.x*b , a.y*b);}
     33 Vector operator/(Vector a , double b){return Vector(a.x/b , a.y/b);}
     34 double operator*(Vector a , Vector b){return a.x*b.y-a.y*b.x;}
     35 
     36 double Dot(Vector a , Vector b){return a.x*b.x+a.y*b.y;}
     37 double Len(Vector a){return sqrt(Dot(a,a));}
     38 int Polxy()
     39 {
     40     sort(po , po+n);
     41     rec[0]=po[0] , rec[1]=po[1];
     42     top=2;
     43     for(int i=2 ; i<n ; i++){
     44         while(top>=2&&(rec[top-1]-rec[top-2])*(po[i]-rec[top-2])<=0)
     45             top--;
     46         rec[top++] = po[i];
     47     }
     48     int tmp=top;
     49     for(int i=n-2 ; i>=0 ; i--){
     50         while(top>=tmp&&(rec[top-1]-rec[top-2])*(po[i]-rec[top-2])<=0)
     51             top--;
     52         rec[top++] = po[i];
     53     }
     54     top--;
     55     return top;
     56 }
     57 
     58 Vector Normal(Vector a)
     59 {
     60     double l = Len(a);
     61     return Vector(-a.y/l , a.x/l);
     62 }
     63 
     64 double calCalip()
     65 {
     66   //  for(int i=0 ; i<top ; i++) rec[i].output();
     67     Point ch[2];
     68     ch[0] = rec[0] , ch[1] = rec[1];
     69     int i1=0 , i2=0 , i3=0;
     70     double maxn = 1e18;
     71     ch[0] = rec[0] , ch[1] = rec[1];
     72     while(dcmp(fabs((rec[(i1+1)%top]-ch[0])*(ch[1]-ch[0]))-fabs((rec[i1]-ch[0])*(ch[1]-ch[0])))>=0) i1=(i1+1)%top;
     73     while(dcmp(Dot(rec[(i2+1)%top]-ch[0] , ch[1]-ch[0])-Dot(rec[i2]-ch[0] , ch[1]-ch[0]))>=0) i2=(i2+1)%top;
     74     while(dcmp(Dot(rec[(i3-1+top)%top]-ch[1] , ch[0]-ch[1])-Dot(rec[i3]-ch[1] , ch[0]-ch[1]))>=0) i3=(i3-1+top)%top;
     75     for(int i=0 ; i<top ; i++){
     76         ch[0] = rec[i] , ch[1] = rec[(i+1)%top];
     77         while(dcmp(fabs((rec[(i1+1)%top]-ch[0])*(ch[1]-ch[0]))-fabs((rec[i1]-ch[0])*(ch[1]-ch[0])))>=0) i1=(i1+1)%top;
     78         while(dcmp(Dot(rec[(i2+1)%top]-ch[0] , ch[1]-ch[0])-Dot(rec[i2]-ch[0] , ch[1]-ch[0]))>=0) i2=(i2+1)%top;
     79         while(dcmp(Dot(rec[(i3+1)%top]-ch[1] , ch[0]-ch[1])-Dot(rec[i3]-ch[1] , ch[0]-ch[1]))>=0) i3=(i3+1)%top;
     80         double l = Len(ch[1]-ch[0]);
     81         double h = fabs((rec[i1]-ch[0])*(ch[1]-ch[0]))/l;
     82         double len1 = Dot(rec[i2]-ch[1] , ch[1]-ch[0])/l; //右侧长度
     83         double len2 = Dot(rec[i3]-ch[0] , ch[0]-ch[1])/l; //左侧长度
     84         double suml = l+len1+len2;
     85        // cout<<i<<" "<<l<<" "<<h<<" "<<len1<<" "<<len2<<" "<<suml*h<<endl;
     86         if(dcmp(suml*h-maxn)<0){
     87             Vector unit1 = (ch[1]-ch[0])/l;
     88             Vector unit2 = Normal(unit1);
     89             maxn = suml*h;
     90             p[0] = ch[1]+unit1*len1;
     91             p[1] = p[0]+unit2*h;
     92             p[2] = p[1]-unit1*suml;
     93             p[3] = p[2]-unit2*h;
     94         }
     95     }
     96     return maxn;
     97 }
     98 
     99 int main()
    100 {
    101    // freopen("in.txt" , "r" , stdin);
    102     while(scanf("%d" , &n)!=EOF)
    103     {
    104         for(int i=0 ; i<n ; i++) po[i].input();
    105         Polxy();
    106         double ret = calCalip();
    107         printf("%.5f
    " , ret);
    108         int st = 0;
    109         for(int i=1 ; i<4 ; i++){
    110             if(p[i].y<p[st].y || (p[i].y==p[st].y&&p[i].x<p[st].x)) st = i;
    111         }
    112         for(int i=0;i<4;i++){
    113             p[st].output();
    114             st = (st+1)%4;
    115         }
    116     }
    117     return 0;
    118 }
  • 相关阅读:
    jquery的$.与$.fn的区别
    jquery加载页面的方法
    创业股权究竟如何分配--新浪创业训练营
    创业者要处理好的10大关系
    洪泰基金投资经理殷鹏:肯定不投的八类项目
    创业初期股权如何分配-------陈楠心血总结
    排序总结
    如何快速进入一门领域,学习新的知识
    虚拟机的设置
    华为大数据项目fusionInsight
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4638694.html
Copyright © 2011-2022 走看看