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 }