【[HNOI2007]最小矩形覆盖】旋转卡壳
旋转卡壳,orz orz orz
由于某个神奇的结论,一定会有一条边在凸壳上,枚举每条凸壳上的边。那么对于这条边的对面有一个对锺点(即高最大,叉积最大),由于显然位置单调,利用叉积卡壳单调枚举即可,类似的可以利用点积最小和最大的点可以找出最左点和最右点,这样就保证可以覆盖所有点,然后略用一点初中几何知识,就可以了。
极度卡精度orz
luogu3187
题目描述
给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形,输出所求矩形的面积和四个顶点坐标输入输出格式
输入格式: 第一行为一个整数n(3<=n<=50000),从第2至第n+1行每行有两个浮点数,表示一个顶点的x和y坐标,不用科学计数法 输出格式: 第一行为一个浮点数,表示所求矩形的面积(精确到小数点后5位),接下来4行每行表示一个顶点坐标,要求第一行为y坐标最小的顶点,其后按逆时针输出顶点坐标.如果用相同y坐标,先输出最小x坐标的顶点输入输出样例
输入样例#1: 复制
6 1.0 3.00000 1 4.00000 2.0000 1 3 0.0000 3.00000 6 6.0 3.0
输出样例#1: 复制
18.00000 3.00000 0.00000 6.00000 3.00000 3.00000 6.00000 0.00000 3.00000
说明
感谢 @intruder 提供题目简述#include<iostream> #include<algorithm> #include<cstdio> #include<cmath> using namespace std; typedef double db; const int maxn = 5e5+5; const db eps = 1e-8; struct node{ db x,y; friend db operator*(node aa,node bb) { return aa.x*bb.x + aa.y*bb.y; } friend node operator*(node aa,db bb) { return (node){aa.x*bb,aa.y*bb}; } friend db operator^(node aa,node bb) { return aa.x*bb.y - aa.y*bb.x; } friend node operator+(node aa,node bb) { return (node){aa.x+bb.x,aa.y+bb.y}; } friend node operator-(node aa,node bb) { return (node){aa.x-bb.x,aa.y-bb.y}; } friend db dis(node aa) { return sqrt(aa.x*aa.x+aa.y*aa.y); } friend db chaji(node aa,node bb,node cc) { return (bb-aa)^(cc-aa); } friend db diji(node aa,node bb,node cc) { return (bb-aa)*(cc-aa); } friend bool CP(node aa,node bb) { // aa < bb ? 1 : 0 if( fabs(aa.y-bb.y)>eps ) return aa.y < bb.y; return aa.x < bb.x; } }z[maxn],s[maxn],as[10]; int tp; db ans=1e18;; bool cmp(node aa,node bb) { return aa.x < bb.x; } int n; void gethull() { sort(z+1,z+1+n,cmp); for(int i=1;i<=n;i++) { while(tp>1&&( (s[tp]-s[tp-1])^(z[i]-s[tp-1]) )<=0 ) tp--; s[++tp] = z[i]; } int tmp = tp; for(int i=n-1;i>=1;i--) { while(tp>tmp&&( (s[tp]-s[tp-1])^(z[i]-s[tp-1]) )<=0) tp--; s[++tp] = z[i]; } --tp; s[tp+1] = s[1]; } void kaker() { int p,l,r; p = l = r = 2; for(int i=1;i<tp;i++) { while( fabs(chaji(s[i],s[i+1],s[p+1])) > fabs(chaji(s[i],s[i+1],s[p])) - eps ) p = p%tp+1; while( diji(s[i],s[i+1],s[r+1]) > diji(s[i],s[i+1],s[r]) - eps ) r = r%tp+1; if(i==1) l = r; while( diji(s[i],s[i+1],s[l+1]) < diji(s[i],s[i+1],s[l]) + eps ) l = l%tp+1; db dd = dis(s[i]-s[i+1]); db lcd = diji(s[i],s[i+1],s[l])/dd; db rcd = diji(s[i],s[i+1],s[r])/dd; db hh = fabs( chaji(s[i],s[i+1],s[p])/dd ); if(ans>hh*(rcd-lcd)) { ans = hh*(rcd-lcd); as[1] = s[i] + (s[i+1]-s[i])*(rcd/dd); as[2] = as[1] + (s[r]-as[1])*(hh/dis(s[r]-as[1])); as[3] = as[2] - (as[1]-s[i])*((rcd-lcd)/rcd); as[4] = as[3] + as[1] - as[2]; } } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lf%lf",&z[i].x,&z[i].y); } gethull(); kaker(); printf("%.5f\n",ans); int fi = 1; for(int i=2;i<=4;i++) { if(CP(as[i],as[fi])) fi = i; } for(int i=fi;i<=4;i++) { printf("%.5f %.5f\n",floor(as[i].x+0.5),floor(as[i].y+0.5) ); } for(int i=1;i<fi;i++) { printf("%.5f %.5f\n",floor(as[i].x+0.5),floor(as[i].y+0.5)); } }