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

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

    枚举一条边,维护上、左、右方的点;

    上方点到这条边距离最远,所以用叉积求面积维护;

    左右点到这条边的射影最长(!),所以用点积求射影维护;

    因为维护的点是只能逆时针走的,所以初始的左边点要特殊处理一下,其实等于右边点即可,然后可以走过去到合适位置;

    然后维护矩形的四个端点,就是根据距离,从边的端点走过去,还挺有意思的;

    注意不要输出 -0;

    然而这其实是假的呵呵,Narh 一拍就出错了,还是很小的数据很明显的错囧

    只是不知道哪里错,怎么调...

    代码如下:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef double db;
    db const eps=1e-8;
    int const xn=50005;
    int n;
    db ans;
    int dmp(db x){if(fabs(x)<=eps)return 0; return x>eps?1:-1;}
    struct P{
      db x,y;
      P(db x=0,db y=0):x(x),y(y) {}
      bool operator < (const P &b) const
      {return dmp(x-b.x)<0||dmp(x-b.x)==0&&dmp(y-b.y)<0;}
      P operator + (const P &b) const
      {return P(x+b.x,y+b.y);}
      P operator - (const P &b) const
      {return P(x-b.x,y-b.y);}
      P operator * (const db &v) const
      {return P(x*v,y*v);}
      P operator / (const db &v) const
      {return P(x/v,y/v);}
    }p[xn],c[xn],pos[5];
    db cross(P a,P b){return a.x*b.y-a.y*b.x;}
    db dot(P a,P b){return a.x*b.x+a.y*b.y;}
    void find()
    {
      sort(p+1,p+n+1); int top=0;
      for(int i=1;i<=n;i++)
        {
          while(top>1&&dmp(cross(c[top]-c[top-1],p[i]-c[top]))<=0)top--;
          c[++top]=p[i];
        }
      int num=top;
      for(int i=n-1;i;i--)
        {
          while(top>num&&dmp(cross(c[top]-c[top-1],p[i]-c[top]))<=0)top--;
          c[++top]=p[i];
        }
      n=top-1;
    }
    int upt(int x){if(x>n)x-=n; if(x<1)x+=n; return x;}
    db sqr(db x){return x*x;}
    db dis(P a,P b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
    bool cmp(P a,P b){return dmp(a.y-b.y)<0||(dmp(a.y-b.y)==0&&dmp(a.x-b.x)<0);}
    void rc()
    {
      ans=-1;
      //int p=2,l=1,r=2;//
      int p=2,l=2,r=2; c[n+1]=c[1];
      for(int i=1;i<=n;i++)
        {
          db d=dis(c[i],c[i+1]);
          while(dmp(cross(c[i]-c[p],c[i+1]-c[p])-cross(c[i]-c[p+1],c[i+1]-c[p+1]))<=0)p=upt(p+1);
          while(dmp(dot(c[r]-c[i],c[i+1]-c[i])-dot(c[r+1]-c[i],c[i+1]-c[i]))<=0)r=upt(r+1);
          if(i==1)l=r;//
          while(dmp(dot(c[l]-c[i],c[i+1]-c[i])-dot(c[l+1]-c[i],c[i+1]-c[i]))>=0)l=upt(l+1);
          db L=dot(c[i+1]-c[i],c[l]-c[i])/d;
          db R=dot(c[i+1]-c[i],c[r]-c[i])/d;
          db H=cross(c[i]-c[p],c[i+1]-c[p])/d;
          db tmp=(R-L)*H;
          if(ans<0||dmp(ans-tmp)>0)
        {
          ans=tmp;
          pos[0]=c[i]+(c[i+1]-c[i])*(R/d);
          pos[1]=pos[0]+(c[r]-pos[0])*(H/dis(c[r],pos[0]));
          //pos[2]=pos[1]+(c[p]-pos[1])*((R-L)/dis(c[p],pos[1]));//也可
          pos[2]=pos[1]+(c[i]-pos[0])*((R-L)/dis(c[i],pos[0]));
          pos[3]=pos[2]+(pos[0]-pos[1]);
        }
        }
    }
    int main()
    {
      scanf("%d",&n);
      for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
      find(); 
      rc();
      printf("%.5f
    ",ans);
      int st=0;
      for(int i=1;i<4;i++)if(cmp(pos[i],pos[st]))st=i;
      for(int i=st,cnt=1;cnt<=4;i=(i+1)%4,cnt++)
        {
          if(fabs(pos[i].x)<=eps)pos[i].x=0;
          if(fabs(pos[i].y)<=eps)pos[i].y=0;
          printf("%.5f %.5f
    ",pos[i].x,pos[i].y);
        }
      return 0;
    }
  • 相关阅读:
    不应滥用named let
    PAT甲级——A1106 Lowest Price in Supply Chain
    PAT甲级——A1105 Spiral Matrix【25】
    PAT甲级——A1104 Sum of Number Segments
    PAT甲级——A1103 Integer Factorization
    PAT甲级——A1102 Invert a Binary Tree
    PAT甲级——A1101 Quick Sort
    PAT甲级——A1100 Mars Numbers
    PAT甲级——A1099 Build A Binary Search Tree
    PAT甲级——A1098 Insertion or Heap Sort
  • 原文地址:https://www.cnblogs.com/Zinn/p/10146990.html
Copyright © 2011-2022 走看看