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\n",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\n",prn[id].x,prn[id].y);
    }
  return 0;
}

 

posted on 2018-12-20 19:34  Narh  阅读(187)  评论(0编辑  收藏  举报

导航