首页 > 代码库 > [BZOJ1185]最小矩形覆盖
[BZOJ1185]最小矩形覆盖
上初三后遇到许多杂事,一度想放弃OI。
然后我就想着省赛随便浪,省赛之前沉迷于几乎不考的计算几何(因为写起来爽啊)
这个是写完模板后的第一题,看了之后感觉思路还挺清晰的。
首先因为它的tag是‘凸包‘,所以我们当然要先求凸包啦~Graham就好了
然后有一个结论是矩形的某一条边一定与凸包的某一条边共线,脑补一下如果不共线,稍微转一下矩形就会更小了。
那么我们枚举每一条凸包上的边x,每次找离x最远的点。
这里可以用二分,只有最远的那个点连接的两条边相对于x一个左转一个右转,把这条性质作为二分依据,就可以愉快地二分啦。
这题的细节处理较为烦人,像我这种弱智调了几天才调好。
代码如下
1 #include<stdio.h>
2 #include<math.h>
3 #include<algorithm>
4 using namespace std;
5 #define dmax 1.7976931348623158e+308
6 #define eps 1e-10
7 struct point{
8 double x,y,ang;
9 int num;
10 }a[100010],t;
11 struct point2{
12 double x,y;
13 point2(){x=y=0;}
14 }ha[100010];
15 int n,i,ori,stack[100010];
16 double miny,minx,orix,oriy,area;
17 point2 p1,p2,p3,p4;
18 double bigger(double x,double y){return x-y>=eps;}
19 double notsm(double x,double y){return bigger(x,y)||abs(x-y)<=eps;}
20 double angle(double x,double y){
21 if(abs(x)<=eps)return dmax;
22 return y/x;
23 }
24 bool cmp(point a,point b){
25 if(bigger(b.ang,a.ang))return 1;
26 if(bigger(a.ang,b.ang))return 0;
27 return bigger(b.x*b.x+b.y*b.y,a.x*a.x+a.y*b.y);
28 }
29 double cross(double ax,double ay,double bx,double by){
30 return ax*by-ay*bx;
31 }
32 int hassium(double vx,double vy,int ll,int rr){
33 int l,r,m;
34 l=ll+1;
35 r=rr-1;
36 while(l<=r){
37 m=(l+r)/2;
38 orix=cross(vx,vy,ha[m].x-ha[m-1].x,ha[m].y-ha[m-1].y);
39 oriy=cross(vx,vy,ha[m+1].x-ha[m].x,ha[m+1].y-ha[m].y);
40 if(orix>=eps){
41 if(oriy>=eps)l=m+1;
42 if(notsm(-oriy,0))return m;
43 }
44 if(abs(orix)<=eps)return m;
45 if(orix<-eps)r=m-1;
46 }
47 }
48 point2 getpoint(double xa,double ya,double x1,double y1,double xb,double yb,double x2,double y2){
49 point2 p;
50 if(abs(x1)<=eps){
51 p.x=xa;
52 p.y=yb;
53 return p;
54 }
55 if(abs(y1)<=eps){
56 p.x=xb;
57 p.y=ya;
58 return p;
59 }
60 p.y=((xb-xa)/x1/x2-yb/x1/y2+ya/x2/y1)/(1./x2/y1-1./x1/y2);
61 p.x=(p.y-ya)/y1*x1+xa;
62 return p;
63 }
64 double recta(double ax,double ay,double bx,double by){
65 return sqrt((ax*ax+ay*ay)*(bx*bx+by*by));
66 }
67 void getrect(double vx,double vy,int num){
68 int farest=hassium(vx,vy,num,num+stack[0]-1);
69 int leftest=hassium(-vy,vx,farest,num+stack[0]-1),rightest=hassium(vy,-vx,num,farest);
70 point2 t1=getpoint(ha[num].x-vx,ha[num].y-vy,vx,vy,ha[rightest].x,ha[rightest].y,vy,-vx),
71 t2=getpoint(ha[rightest].x,ha[rightest].y,-vy,vx,ha[farest].x,ha[farest].y,vx,vy),
72 t3=getpoint(ha[leftest].x,ha[leftest].y,-vy,vx,ha[farest].x,ha[farest].y,-vx,-vy),
73 t4=getpoint(ha[leftest].x,ha[leftest].y,vy,-vx,ha[num].x,ha[num].y,-vx,-vy);
74 double tarea=recta(t2.x-t1.x,t2.y-t1.y,t4.x-t1.x,t4.y-t1.y);
75 if(bigger(area,tarea)){
76 area=tarea;
77 p1=t1;
78 p2=t2;
79 p3=t3;
80 p4=t4;
81 }
82 }
83 bool comp(point2 a,point2 b,point2 c,point2 d){
84 return((bigger(b.y,a.y))||(abs(a.y-b.y)<=eps&&bigger(b.x,a.x)))
85 &&((bigger(c.y,a.y))||(abs(a.y-c.y)<=eps&&bigger(c.x,a.x)))
86 &&((bigger(d.y,a.y))||(abs(a.y-d.y)<=eps&&bigger(d.x,a.x)));
87 }
88 void gao(point2&a){
89 if(a.x<0&&abs(a.x)<=1e-5)a.x=-a.x;
90 if(a.y<0&&abs(a.y)<=1e-5)a.y=-a.y;
91 }
92 int main(){
93 scanf("%d",&n);
94 miny=minx=dmax;
95 for(i=1;i<=n;i++){
96 scanf("%lf%lf",&a[i].x,&a[i].y);
97 a[i].num=i;
98 if((a[i].x==minx&&a[i].y<miny)||a[i].x<minx){
99 miny=a[i].y;
100 minx=a[i].x;
101 ori=i;
102 }
103 }
104 orix=a[ori].x;
105 oriy=a[ori].y;
106 for(i=1;i<=n;i++){
107 a[i].x-=orix;
108 a[i].y-=oriy;
109 if(i!=ori)
110 a[i].ang=angle(a[i].x,a[i].y);
111 }
112 t=a[1];
113 a[1]=a[ori];
114 a[ori]=t;
115 sort(a+2,a+n+1,cmp);
116 stack[0]=2;
117 stack[1]=1;
118 stack[2]=2;
119 for(i=3;i<=n;i++){
120 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,
121 a[i].x-a[stack[stack[0]]].x,a[i].y-a[stack[stack[0]]].y)<=0)stack[0]--;
122 stack[0]++;
123 stack[stack[0]]=i;
124 }
125 for(i=1;i<=n;i++){
126 a[i].x+=orix;
127 a[i].y+=oriy;
128 }
129 for(i=1;i<=stack[0];i++){
130 ha[i].x=a[stack[i]].x;
131 ha[i].y=a[stack[i]].y;
132 }
133 area=dmax;
134 getrect(ha[1].x-ha[stack[0]].x,ha[1].y-ha[stack[0]].y,1);
135 for(i=1;i<stack[0];i++){
136 ha[i+stack[0]]=ha[i];
137 getrect(ha[i+1].x-ha[i].x,ha[i+1].y-ha[i].y,i+1);
138 }
139 gao(p1);
140 gao(p2);
141 gao(p3);
142 gao(p4);
143 printf("%.5lf\n",area);
144 if(comp(p1,p2,p3,p4))
145 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);
146 if(comp(p2,p1,p3,p4))
147 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);
148 if(comp(p3,p2,p1,p4))
149 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);
150 if(comp(p4,p2,p3,p1))
151 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);
152 }
[BZOJ1185]最小矩形覆盖
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。