bzoj1185 [HNOI2007]最小矩形覆盖

Description

 

正解:凸包+旋转卡壳。

这道题思路也是比较显然的。首先我们可以想到,最小矩形的一条边肯定是凸包上的一条边。然后我们用旋转卡壳枚举每一条边,并算出距离这条边最远的点,左边最远的点和右边最远的点,然后用一下叉积点积什么的算出面积和点就行了。

比较坑的是,答案可能会爆成$-0.00000$,然后必须加一个特判才行。

 

  1 //It is made by wfj_2048~
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <cstring>
  5 #include <cstdlib>
  6 #include <cstdio>
  7 #include <vector>
  8 #include <cmath>
  9 #include <queue>
 10 #include <stack>
 11 #include <map>
 12 #include <set>
 13 #define inf (1<<30)
 14 #define N (100010)
 15 #define eps (1e-8)
 16 #define il inline
 17 #define RG register
 18 #define ll long long
 19 #define ld long double
 20 
 21 using namespace std;
 22 
 23 int n,top;
 24 ld ans;
 25 
 26 struct point{
 27     
 28     ld x,y;
 29     
 30     il bool operator == (const point &a) const{
 31     return x==a.x && y==a.y;
 32     }
 33     
 34     il bool operator < (const point &a) const{
 35     if (x==a.x) return y<a.y; return x<a.x;
 36     }
 37 
 38     il point operator + (const point &a) const{
 39     return (point){x+a.x,y+a.y};
 40     }
 41 
 42     il point operator - (const point &a) const{
 43     return (point){x-a.x,y-a.y};
 44     }
 45 
 46     il point operator * (const ld &v) const{
 47     return (point){x*v,y*v};
 48     }
 49 
 50     il point operator / (const ld &v) const{
 51     return (point){x/v,y/v};
 52     }
 53     
 54 }p[N],st[N],po[5],Ans;
 55 
 56 il ld dot(RG point a,RG point b){ return a.x*b.x+a.y*b.y; }
 57 
 58 il ld cross(RG point a,RG point b){ return a.x*b.y-a.y*b.x; }
 59 
 60 il ld dis(RG point a,RG point b){
 61     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
 62 }
 63 
 64 il point get(RG point p,RG point a,RG point b){
 65     RG point v=b-a; return a+v*dot(v,p-a)/dot(v,v);
 66 }
 67 
 68 il int cmp1(const point &a,const point &b){
 69     if (a.y==b.y) return a.x<b.x; return a.y<b.y;
 70 }
 71 
 72 il int cmp2(const point &a,const point &b){
 73     return atan2(a.y-Ans.y,a.x-Ans.x)<atan2(b.y-Ans.y,b.x-Ans.x);
 74 }
 75 
 76 il int gi(){
 77     RG int x=0,q=1; RG char ch=getchar();
 78     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
 79     if (ch=='-') q=-1,ch=getchar();
 80     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
 81     return q*x;
 82 }
 83 
 84 int main(){
 85 #ifndef ONLINE_JUDGE
 86     freopen("square.in","r",stdin);
 87     freopen("square.out","w",stdout);
 88 #endif
 89     n=gi(); for (RG int i=1;i<=n;++i) scanf("%Lf%Lf",&p[i].x,&p[i].y);
 90     sort(p+1,p+n+1),st[++top]=p[1];
 91     for (RG int i=2;i<=n;++i){
 92     while (top>=2 && cross(st[top]-st[top-1],p[i]-st[top-1])<eps) --top;
 93     st[++top]=p[i];
 94     }
 95     RG int la=top,l,r=2,pos=2; ans=1e100;
 96     for (RG int i=n-1;i;--i){
 97     while (top>la && cross(st[top]-st[top-1],p[i]-st[top-1])<eps) --top;
 98     st[++top]=p[i];
 99     }
100     for (RG int i=1;i<top;++i){
101     RG ld D=dis(st[i],st[i+1]);
102     while (cross(st[i+1]-st[i],st[pos+1]-st[i])>=cross(st[i+1]-st[i],st[pos]-st[i])) pos=pos%(top-1)+1;
103     while (dot(st[i+1]-st[i],st[r+1]-st[i])>=dot(st[i+1]-st[i],st[r]-st[i])) r=r%(top-1)+1; if (i==1) l=r;
104     while (dot(st[i+1]-st[i],st[l+1]-st[i])<=dot(st[i+1]-st[i],st[l]-st[i])) l=l%(top-1)+1;
105     RG ld L=dot(st[i+1]-st[i],st[l]-st[i])/D,R=dot(st[i+1]-st[i],st[r]-st[i])/D;
106     RG ld H=cross(st[i+1]-st[i],st[pos]-st[i])/D,res=H*(R-L); if (res<0) res=-res;
107     if (ans>res){
108         ans=res;
109         po[1]=st[i]+(st[i+1]-st[i])*(R/D);
110         po[2]=st[i]+(st[i+1]-st[i])*(L/D);
111         po[3]=po[1]+(st[r]-po[1])*(H/dis(po[1],st[r]));
112         po[4]=po[2]+po[3]-po[1];
113         if (po[1].x<eps && po[1].x>-eps) po[1].x=fabs(po[1].x);
114         if (po[1].y<eps && po[1].y>-eps) po[1].y=fabs(po[1].y);
115         if (po[2].x<eps && po[2].x>-eps) po[2].x=fabs(po[2].x);
116         if (po[2].y<eps && po[2].y>-eps) po[2].y=fabs(po[2].y);
117         if (po[3].x<eps && po[3].x>-eps) po[3].x=fabs(po[3].x);
118         if (po[3].y<eps && po[3].y>-eps) po[3].y=fabs(po[3].y);
119         if (po[4].x<eps && po[4].x>-eps) po[4].x=fabs(po[4].x);
120         if (po[4].y<eps && po[4].y>-eps) po[4].y=fabs(po[4].y);
121     }
122     }
123     printf("%0.5Lf\n",ans),sort(po+1,po+5,cmp1),Ans=po[1]; sort(po+1,po+5,cmp2);
124     for (RG int i=1;i<=4;++i) printf("%0.5Lf %0.5Lf\n",po[i].x,po[i].y);
125     return 0;
126 }

 

posted @ 2017-08-01 09:27  wfj_2048  阅读(338)  评论(0编辑  收藏  举报