【[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));
}
}

浙公网安备 33010602011771号