[BZOJ1185]最小矩形覆盖
2017-08-07 11:59
239 查看
省赛之前沉迷于几乎不考的计算几何(我大概是没救了)
这个是写完模板后的第一题,看了之后感觉思路还挺清晰的。
首先因为它的tag是'凸包',所以我们当然要先求凸包啦~Graham就好了
然后有一个结论是矩形的某一条边一定与凸包的某一条边共线,脑补一下如果不共线,稍微转一下矩形就会更小了。
那么我们枚举每一条凸包上的边$x$,每次找离x最远的点。
这里可以用二分,只有最远的那个点连接的两条边相对于$x$一个左转一个右转,把这条性质作为二分依据,就可以愉快地二分啦。
这题的细节处理较为烦人,像我这种弱智调了几天才调好。
这个是写完模板后的第一题,看了之后感觉思路还挺清晰的。
首先因为它的tag是'凸包',所以我们当然要先求凸包啦~Graham就好了
然后有一个结论是矩形的某一条边一定与凸包的某一条边共线,脑补一下如果不共线,稍微转一下矩形就会更小了。
那么我们枚举每一条凸包上的边$x$,每次找离x最远的点。
这里可以用二分,只有最远的那个点连接的两条边相对于$x$一个左转一个右转,把这条性质作为二分依据,就可以愉快地二分啦。
这题的细节处理较为烦人,像我这种弱智调了几天才调好。
#include<stdio.h> #include<math.h> #include<algorithm> using namespace std; #define dmax 1.7976931348623158e+308 #define eps 1e-10 struct point{ double x,y,ang; int num; }a[100010],t; struct point2{ double x,y; point2(){x=y=0;} }ha[100010]; int n,i,ori,stack[100010]; double miny,minx,orix,oriy,area; point2 p1,p2,p3,p4; double bigger(double x,double y){return x-y>=eps;} double notsm(double x,double y){return bigger(x,y)||abs(x-y)<=eps;} double angle(double x,double y){ if(abs(x<=eps))return dmax; return y/x; } bool cmp(point a,point b){ if(bigger(b.ang,a.ang))return 1; if(bigger(a.ang,b.ang))return 0; return bigger(b.x*b.x+b.y*b.y,a.x*a.x+a.y*b.y); } double cross(double ax,double ay,double bx,double by){ return ax*by-ay*bx; } int hassium(double vx,double vy,int ll,int rr){ int l,r,m; l=ll+1; r=rr-1; while(l<=r){ m=(l+r)/2; orix=cross(vx,vy,ha[m].x-ha[m-1].x,ha[m].y-ha[m-1].y); oriy=cross(vx,vy,ha[m+1].x-ha[m].x,ha[m+1].y-ha[m].y); if(orix>=eps){ if(oriy>=eps)l=m+1; if(notsm(-oriy,0))return m; } if(abs(orix)<=eps)return m; if(orix<-eps)r=m-1; } } point2 getpoint(double xa,double ya,double x1,double y1,double xb,double yb,double x2,double y2){ point2 p; if(abs(x1)<=eps){ p.x=xa; p.y=yb; return p; } if(abs(y1)<=eps){ p.x=xb; p.y=ya; return p; } p.y=((xb-xa)/x1/x2-yb/x1/y2+ya/x2/y1)/(1./x2/y1-1./x1/y2); p.x=(p.y-ya)/y1*x1+xa; return p; } double recta(double ax,double ay,double bx,double by){ return sqrt((ax*ax+ay*ay)*(bx*bx+by*by)); } void getrect(double vx,double vy,int num){ int farest=hassium(vx,vy,num,num+stack[0]-1); int leftest=hassium(-vy,vx,farest,num+stack[0]-1),rightest=hassium(vy,-vx,num,farest); point2 t1=getpoint(ha[num].x-vx,ha[num].y-vy,vx,vy,ha[rightest].x,ha[rightest].y,vy,-vx), t2=getpoint(ha[rightest].x,ha[rightest].y,-vy,vx,ha[farest].x,ha[farest].y,vx,vy), t3=getpoint(ha[leftest].x,ha[leftest].y,-vy,vx,ha[farest].x,ha[farest].y,-vx,-vy), t4=getpoint(ha[leftest].x,ha[leftest].y,vy,-vx,ha[num].x,ha[num].y,-vx,-vy); double tarea=recta(t2.x-t1.x,t2.y-t1.y,t4.x-t1.x,t4.y-t1.y); if(bigger(area,tarea)){ area=tarea; p1=t1; p2=t2; p3=t3; p4=t4; } } bool comp(point2 a,point2 b,point2 c,point2 d){ return((bigger(b.y,a.y))||(abs(a.y-b.y)<=eps&&bigger(b.x,a.x))) &&((bigger(c.y,a.y))||(abs(a.y-c.y)<=eps&&bigger(c.x,a.x))) &&((bigger(d.y,a.y))||(abs(a.y-d.y)<=eps&&bigger(d.x,a.x))); } void gao(point2&a){ if(a.x<0&&abs(a.x)<=1e-5)a.x=-a.x; if(a.y<0&&abs(a.y)<=1e-5)a.y=-a.y; } int main(){ scanf("%d",&n); miny=minx=dmax; for(i=1;i<=n;i++){ scanf("%lf%lf",&a[i].x,&a[i].y); a[i].num=i; if((a[i].x==minx&&a[i].y<miny)||a[i].x<minx){ miny=a[i].y; minx=a[i].x; ori=i; } } orix=a[ori].x; oriy=a[ori].y; for(i=1;i<=n;i++){ a[i].x-=orix; a[i].y-=oriy; if(i!=ori) a[i].ang=angle(a[i].x,a[i].y); } t=a[1]; a[1]=a[ori]; a[ori]=t; sort(a+2,a+n+1,cmp); stack[0]=2; stack[1]=1; stack[2]=2; for(i=3;i<=n;i++){ while(stack[0]>1&&cross(a[stack[stack[0]]].x-a[stack[stack[0]-1]].x,a[stack[stack[0]]].y-a[stack[stack[0]-1]].y, a[i].x-a[stack[stack[0]]].x,a[i].y-a[stack[stack[0]]].y)<=0)stack[0]--; stack[0]++; stack[stack[0]]=i; } for(i=1;i<=n;i++){ a[i].x+=orix; a[i].y+=oriy; } for(i=1;i<=stack[0];i++){ ha[i].x=a[stack[i]].x; ha[i].y=a[stack[i]].y; } area=dmax; getrect(ha[1].x-ha[stack[0]].x,ha[1].y-ha[stack[0]].y,1); for(i=1;i<stack[0];i++){ ha[i+stack[0]]=ha[i]; getrect(ha[i+1].x-ha[i].x,ha[i+1].y-ha[i].y,i+1); } gao(p1); gao(p2); gao(p3); gao(p4); printf("%.5lf\n",area); if(comp(p1,p2,p3,p4)) printf("%.5lf %.5lf\n%.5lf %.5lf\n%.5lf %.5lf\n%.5lf %.5lf\n",p1.x,p1.y,p2.x,p2.y,p3.x,p3.y,p4.x,p4.y); if(comp(p2,p1,p3,p4)) printf("%.5lf %.5lf\n%.5lf %.5lf\n%.5lf %.5lf\n%.5lf %.5lf\n",p2.x,p2.y,p3.x,p3.y,p4.x,p4.y,p1.x,p1.y); if(comp(p3,p2,p1,p4)) printf("%.5lf %.5lf\n%.5lf %.5lf\n%.5lf %.5lf\n%.5lf %.5lf\n",p3.x,p3.y,p4.x,p4.y,p1.x,p1.y,p2.x,p2.y); if(comp(p4,p2,p3,p1)) printf("%.5lf %.5lf\n%.5lf %.5lf\n%.5lf %.5lf\n%.5lf %.5lf\n",p4.x,p4.y,p1.x,p1.y,p2.x,p2.y,p3.x,p3.y); }
相关文章推荐
- 【旋转卡壳+凸包】BZOJ1185:[HNOI2007]最小矩形覆盖
- [BZOJ1185][HNOI2007]最小矩形覆盖(凸包+旋转卡壳)
- BZOJ 1185 [HNOI2007]最小矩形覆盖 旋转卡壳
- BZOJ 1185 最小矩形覆盖
- BZOJ1185 [HNOI2007]最小矩形覆盖
- [省选前题目整理][BZOJ 1185][HNOI 2007]最小矩形覆盖(旋转卡壳)
- 1185: [HNOI2007]最小矩形覆盖 - BZOJ
- ●BZOJ 1185 [HNOI2007]最小矩形覆盖
- 【HNOI2007】bzoj1185 最小矩形覆盖
- BZOJ1185 [HNOI2007]最小矩形覆盖
- 【BZOJ1185】最小矩形覆盖 计算几何 凸包 旋转卡壳
- bzoj1185[HNOI2007]最小矩形覆盖
- BZOJ 1185 HNOI 2007 最小矩形覆盖 旋转卡壳
- BZOJ:1185: [HNOI2007]最小矩形覆盖
- [BZOJ 1185][HNOI 2007]最小矩形覆盖(凸包+旋转卡壳)
- bzoj1185 [HNOI2007]最小矩形覆盖
- BZOJ 1185 [HNOI2007]最小矩形覆盖
- bzoj 1185 [HNOI2007]最小矩形覆盖 凸包+旋转卡壳
- bzoj 1185 [HNOI2007]最小矩形覆盖(坑)