Bzoj1185 [HNOI2007]最小矩形覆盖
Submit: 1653 Solved: 745
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
Sample Output
HINT
Source
数学问题 计算几何 旋转卡壳
按顺序枚举凸包上每一条边为底边,旋转卡壳找出此时的矩形的顶点、最左点和最右点,花式计算出边长,求面积,记录面积最小值和对应的解。
式子都能看懂,但不看题解就是写不出来,沮丧。
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int INF=0x3f3f3f3f; 10 const double eps=1e-8; 11 const int mxn=100010; 12 int read(){ 13 int x=0,f=1;char ch=getchar(); 14 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 15 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 16 return x*f; 17 } 18 inline int DT(double x){ 19 if(abs(x)<eps)return 0; 20 else return x<0?-1:1; 21 } 22 struct point{ 23 double x,y; 24 point operator + (point b){return (point){x+b.x,y+b.y};} 25 point operator - (point b){return (point){x-b.x,y-b.y};} 26 point operator * (double v){return (point){x*v,y*v};} 27 point operator / (double v){return (point){x/v,y/v};} 28 bool operator < (point b)const{ 29 return x<b.x || (x==b.x && y<b.y); 30 } 31 }a[mxn],p[mxn],ans[5]; 32 typedef point Vector; 33 double dot (point a,point b){return a.x*b.x+a.y*b.y;} 34 double Cross(point a,point b){ 35 return a.x*b.y-a.y*b.x; 36 } 37 double dist(point a,point b){ 38 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 39 } 40 double Len(point a){ 41 return sqrt((a.x*a.x)+(a.y*a.y)); 42 } 43 double DLC(point p,point a,point b){ 44 Vector v1=p-a,v2=b-a; 45 return fabs(Cross(v1,v2)/Len(v2)); 46 } 47 int n; 48 double ANS=0; 49 int st[mxn],top=0,t2=0; 50 void Andrew(){ 51 sort(p+1,p+n+1); 52 for(int i=1;i<=n;i++){ 53 while(top>1 && Cross(p[st[top]]-p[st[top-1]],p[i]-p[st[top-1]])<=0)top--; 54 st[++top]=i; 55 } 56 t2=top; 57 for(int i=n-1;i;i--){ 58 while(t2>top && Cross(p[st[t2]]-p[st[t2-1]],p[i]-p[st[t2-1]])<=0)t2--; 59 st[++t2]=i; 60 } 61 if(n>1)t2--; 62 n=t2; 63 for(int i=1;i<=n;i++){ 64 a[i]=p[st[i]]; 65 } 66 return; 67 } 68 void solve(){ 69 ANS=(double)INF; 70 a[n+1]=a[1]; 71 int l=1,r=1,tmp=1; 72 double H,D,L,R; 73 for(int i=1;i<=n;i++){ 74 while(DT(DLC(a[tmp],a[i],a[i+1])-DLC(a[tmp+1],a[i],a[i+1]))<=0)tmp=tmp%n+1;//顶部 75 while(DT(dot(a[i+1]-a[i],a[l]-a[i])-dot(a[i+1]-a[i],a[l+1]-a[i]))<=0)l=l%n+1;//左边 76 if(i==1)r=tmp; 77 while(DT(dot(a[i+1]-a[i],a[r]-a[i])-dot(a[i+1]-a[i],a[r+1]-a[i]))>=0)r=r%n+1;//右边 78 // printf("i:%d l:%d tmp:%d r:%d\n",i,l,tmp,r); 79 L=dist(a[i+1],a[i]); 80 // H=fabs(Cross(a[tmp]-a[i],a[i+1]-a[i]))/L;//高 81 H=DLC(a[tmp],a[i],a[i+1]); 82 D=fabs(dot(a[i+1]-a[i],a[l]-a[i])/L)+fabs(dot(a[i+1]-a[i],a[r]-a[i])/L);//底边长 83 R=H*D; 84 // printf("L:%.3f H:%.3f D:%.3f R:%.3f\n",L,H,D,R); 85 if(R<ANS){//更新答案 86 ANS=R; 87 Vector v=(a[i+1]-a[i])/L;//单位长度 88 Vector u=(point){-v.y,v.x};//v逆时针转90度 89 ans[1]=a[i]+v*dot(a[r]-a[i],v); 90 ans[2]=a[i]+v*dot(a[l]-a[i],v); 91 ans[3]=ans[2]+u*H; 92 ans[4]=ans[1]+u*H; 93 } 94 } 95 return; 96 } 97 int main(){ 98 // freopen("in.txt","r",stdin); 99 int i,j; 100 scanf("%d",&n); 101 for(i=1;i<=n;i++){ 102 scanf("%lf%lf",&p[i].x,&p[i].y); 103 } 104 Andrew(); 105 /* printf("n:%d\n",n); 106 for(i=1;i<=n;i++){ 107 printf("%.3f %.3f\n",a[i].x,a[i].y); 108 }*/ 109 solve(); 110 int pos=1; 111 for(i=1;i<=4;i++){ 112 if(ans[i].y<eps)ans[i].y=0; 113 if(ans[i].x<eps)ans[i].x=0; 114 if(ans[i].y<ans[pos].y || (ans[i].y==ans[pos].y && ans[i].x<ans[pos].x))pos=i; 115 } 116 if(ANS<eps)ANS=0; 117 printf("%.5f\n",ANS); 118 for(i=pos;i<=4;i++) 119 printf("%.5f %.5f\n",ans[i].x,ans[i].y); 120 for(i=1;i<pos;i++) 121 printf("%.5f %.5f\n",ans[i].x,ans[i].y); 122 return 0; 123 }
本文为博主原创文章,转载请注明出处。