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

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

    矩形一定贴着凸包的一条边。不过只是感觉这样。

    枚举一条边,对面的点就是正常的旋转卡壳。两边的那个点可以用点积的最小/大来判断,因为是投影。

    然后调了一万年。不过好像把精度设成 1e-13 而不是 1e-8 就能过了。

    和许多代码对拍,有各种各样的不同。也不知道自己是不是真的对了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define db double
    using namespace std;
    const int N=5e4+5;const db eps=1e-13,INF=1e18;
    int n,tot; db ans;
    struct Node{
      db x,y;
      Node(db a=0,db b=0):x(a),y(b) {}
      bool operator< (const Node &b)const {return x<b.x||(x==b.x&&y<b.y);}
      Node operator- (const Node &b)const {return Node(x-b.x,y-b.y);}
      Node operator+ (const Node &b)const {return Node(x+b.x,y+b.y);}
      db operator* (const Node &b)const {return x*b.x+y*b.y;}
      Node operator* (const db &b)const {return Node(x*b,y*b);}
      Node operator/ (const db &b)const {return Node(x/b,y/b);}
    }t[N],a[N],prn[5];
    db Mx(db a,db b){return a>b?a:b;}
    int dcmp(db x){if(x>eps)return 1;if(x<-eps)return -1;return 0;}
    db cross(Node u,Node v){return u.x*v.y-u.y*v.x;}
    void upd(int &x){x>n?x-=n:0;}
    db Sqr(db x){return x*x;}
    db dist(Node u,Node v){return sqrt(Sqr(u.x-v.x)+Sqr(u.y-v.y));}
    int main()
    {
      scanf("%d",&tot);
      for(int i=1;i<=tot;i++)scanf("%lf%lf",&t[i].x,&t[i].y);
      sort(t+1,t+tot+1);
      for(int i=1;i<=tot;i++)
        {while(n>1&&dcmp(cross(a[n]-t[i],a[n-1]-t[i]))>=0)n--;a[++n]=t[i];}
      for(int i=tot-1,lm=n;i;i--)
        {while(n>lm&&dcmp(cross(a[n]-t[i],a[n-1]-t[i]))>=0)n--;a[++n]=t[i];}
      a[n]=a[1]; n--; ans=INF;
      int p0=2,cr=2,p1=3;//out of for()
      for(int i=1;i<=n;i++)
        {
          Node d=a[i+1]-a[i];
          while(dcmp(cross(d,a[cr+1]-a[i])-cross(d,a[cr]-a[i]))>0)cr++,upd(cr);
          while(dcmp((a[p0+1]-a[i])*d-(a[p0]-a[i])*d)>=0)p0++,upd(p0);//>=?
          if(i==1)p1=cr;//
          while(dcmp((a[p1+1]-a[i])*d-(a[p1]-a[i])*d)<=0)p1++,upd(p1);
    
          db len=dist(a[i+1],a[i]);
          db s1=(a[p0]-a[i])*d/len, s2=(a[p1]-a[i])*d/len;
          db hi=cross(d,a[cr]-a[i])/len, ara=(s1-s2)*hi;//not /(2*len)
          if(dcmp(ara-ans)>=0)continue; ans=ara;
          //      if(ara>=ans)continue; ans=ara;
          Node x1=d/len*(s1-s2);
          Node x2=d/len*hi; swap(x2.x,x2.y); x2.x=-x2.x;//*i
          prn[1]=a[i]+d/len*s2;  prn[2]=prn[1]+x1;
          prn[3]=prn[2]+x2; prn[4]=prn[1]+x2;
        }
      printf("%.5f
    ",ans);int id=1;
      for(int i=2;i<=4;i++)
        {
          Node u=prn[i],v=prn[id];
          if(dcmp(u.y-v.y)<0||(!dcmp(u.y-v.y)&&dcmp(u.x-v.x)<0))id=i;
        }
      for(int j=1;j<=4;j++,id++,id>4?id=1:0)
        {
          if(!dcmp(prn[id].x))prn[id].x=0;
          if(!dcmp(prn[id].y))prn[id].y=0;//avoid -0
          printf("%.5f %.5f
    ",prn[id].x,prn[id].y);
        }
      return 0;
    }
  • 相关阅读:
    mysql报错:java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone.
    MD5登陆密码的生成
    15. 3Sum、16. 3Sum Closest和18. 4Sum
    11. Container With Most Water
    8. String to Integer (atoi)
    6. ZigZag Conversion
    5. Longest Palindromic Substring
    几种非线性激活函数介绍
    AI初探1
    AI初探
  • 原文地址:https://www.cnblogs.com/Narh/p/10151784.html
Copyright © 2011-2022 走看看