求出凸包后,矩形的一条边一定与凸包的某条边重合。

枚举每条边,求出离它最远的点和离它最左最右的点,因为那三个点是单调变化的,所以复杂度为$O(n)$。

注意精度。

#include<cstdio>
#include<algorithm>
#include<cmath>
#define N 50010
using namespace std;
typedef double D;
struct P{D x,y;P(){}P(D _x,D _y){x=_x,y=_y;}}p[N],pp[N],hull[N],pivot,A,B,C,rect[8];
int n,i,j,l,r,k;
D w,h,ans=1e20,tmp,len;
bool del[N];
inline int zero(D x){return fabs(x)<1e-4;}
inline int sig(D x){if(fabs(x)<1e-8)return 0;return x>0?1:-1;}
inline D cross(P A,P B,P C){return(B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x);}
inline D distsqr(P A,P B){return(A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);}
inline bool cmp(P a,P b){
D t=cross(pivot,a,b);
return sig(t)==1||sig(t)==0&&sig(distsqr(pivot,a)-distsqr(pivot,b))==-1;
}
inline void convexhull(int n,P stck[],int&m){
int i,k,top;
for(i=0;i<n;i++)pp[i]=p[i];
for(k=0,i=1;i<n;i++)if(pp[i].y<pp[k].y||(pp[i].y==pp[k].y&&pp[i].x<pp[k].x))k=i;
pivot=pp[k];pp[k]=pp[0];pp[0]=pivot;
sort(pp+1,pp+n,cmp);
stck[0]=pp[0];stck[1]=pp[1];
for(top=1,i=2;i<n;i++){
while(top&&sig(cross(pp[i],stck[top],stck[top-1]))>=0)--top;
stck[++top]=pp[i];
}
m=top+1;
}
inline D area(P A,P B,P C){return fabs(cross(A,B,C));}
inline P vertical(P A,P B){return P(A.x-B.y+A.y,A.y+B.x-A.x);}
int main(){
scanf("%d",&n);
for(i=0;i<n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
convexhull(n,hull,n);
for(i=1;i<n;i++)if(zero(hull[i].x-hull[i-1].x)&&zero(hull[i].y-hull[i-1].y))del[i]=1;
for(k=i=0;i<n;i++)if(!del[i])hull[k++]=hull[i];
for(hull[n=k]=hull[i=0];i<n;i++){
A=hull[i],B=hull[i+1],C=vertical(A,B);
while(sig(area(A,B,hull[j])-area(A,B,hull[j+1]))<1)j=(j+1)%n;
while(sig(cross(A,C,hull[l])-cross(A,C,hull[l+1]))<1)l=(l+1)%n;
while(sig(cross(A,C,hull[r])-cross(A,C,hull[r+1]))>-1)r=(r+1)%n;
len=sqrt(distsqr(A,B));
h=area(A,B,hull[j])/len;
w=(cross(A,C,hull[l])-cross(A,C,hull[r]))/len;
if(sig(h*w-ans)==-1){
ans=h*w;
tmp=area(A,B,hull[l])/len/len;
rect[0]=P(hull[l].x+tmp*(A.x-C.x),hull[l].y+tmp*(A.y-C.y));
tmp=h/len;
rect[3]=P(rect[0].x+tmp*(C.x-A.x),rect[0].y+tmp*(C.y-A.y));
tmp=w/len;
rect[1]=P(rect[0].x+tmp*(B.x-A.x),rect[0].y+tmp*(B.y-A.y));
rect[2]=P(rect[3].x+tmp*(B.x-A.x),rect[3].y+tmp*(B.y-A.y));
}
}
for(i=0;i<4;i++)rect[i+4]=rect[i];
for(j=0,i=1;i<4;i++)if(sig(rect[i].y-rect[j].y)==-1||sig(rect[i].y-rect[j].y)==0&&sig(rect[i].x-rect[j].x)==-1)j=i;
printf("%.0f.00000\n",ans);
for(i=0;i<4;i++)printf("%.0f.00000 %.0f.00000\n",rect[j+i].x,rect[j+i].y);
return 0;
}

  

BZOJ1185 : [HNOI2007]最小矩形覆盖的更多相关文章

  1. BZOJ1185[HNOI2007] 最小矩形覆盖(旋转卡壳)

    BZOJ1185[HNOI2007] 最小矩形覆盖 题面 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形,输出所求矩形的面积和四个顶点的坐标 分析 首先可以先求凸包,因为覆盖了凸包上的顶点,凸 ...

  2. bzoj1185 [HNOI2007]最小矩形覆盖 旋转卡壳求凸包

    [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 2081  Solved: 920 ...

  3. BZOJ1185 [HNOI2007]最小矩形覆盖 【旋转卡壳】

    题目链接 BZOJ1185 题解 最小矩形一定有一条边在凸包上,枚举这条边,然后旋转卡壳维护另外三个端点即可 计算几何细节极多 维护另外三个端点尽量不在这条边上,意味着左端点尽量靠后,右端点尽量靠前, ...

  4. 2018.10.18 bzoj1185: [HNOI2007]最小矩形覆盖(旋转卡壳)

    传送门 不难看出最后的矩形一定有一条边与凸包某条边重合. 因此先求出凸包,然后旋转卡壳求出当前最小矩形面积更新答案. 代码: #include<bits/stdc++.h> #define ...

  5. [BZOJ1185][HNOI2007]最小矩形覆盖-[凸包+旋转卡壳]

    Description 传送门 Solution 感性理解一下,最小矩形一定是由一条边和凸包上的边重合的. 然后它就是模板题了..然而真的好难调,小于大于动不动就打错. Code #include&l ...

  6. BZOJ1185 HNOI2007 最小矩形覆盖 凸包、旋转卡壳

    传送门 首先,肯定只有凸包上的点会限制这个矩形,所以建立凸包. 然后可以知道,矩形上一定有一条边与凸包上的边重合,否则可以转一下使得它重合,答案会更小. 于是沿着凸包枚举这一条边,通过旋转卡壳找到离这 ...

  7. bzoj千题计划209:bzoj1185: [HNOI2007]最小矩形覆盖

    http://www.lydsy.com/JudgeOnline/problem.php?id=1185 题解去看它 http://www.cnblogs.com/TheRoadToTheGold/p ...

  8. 【BZOJ1185】[HNOI2007]最小矩形覆盖(凸包,旋转卡壳)

    [BZOJ1185][HNOI2007]最小矩形覆盖(凸包,旋转卡壳) 题面 BZOJ 洛谷 题解 最小的矩形一定存在一条边在凸包上,那么枚举这条边,我们还差三个点,即距离当前边的最远点,以及做这条边 ...

  9. 【旋转卡壳+凸包】BZOJ1185:[HNOI2007]最小矩形覆盖

    1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 1945  Solve ...

随机推荐

  1. [OpenJudge 3063]罪犯问题

    [OpenJudge 3063]罪犯问题 试题描述 一天,警官抓获了N个嫌犯,审问N个罪犯的途中,作为警长助手的你突然发现其中被确定为罪犯的K号人是你曾经出生入死的兄弟,你不能眼睁睁看着他被抓进牢里. ...

  2. 【转】基于注解的SpirngMVC简单介绍

    转载地址:http://haohaoxuexi.iteye.com/blog/1343761 SpringMVC是一个基于DispatcherServlet的MVC框架,每一个请求最先访问的都是 Di ...

  3. kettle作业中的js如何写日志文件

    在kettle作业中JavaScript脚本有时候也扮演非常重要的角色,此时我们希望有一些日志记录.下面是job中JavaScript记录日志的方式. job的js写日志的方法. 得到日志输出实例 o ...

  4. c++标准库中几个常见的数据结构的区别和应用规则

    转载自http://www.lifecrunch.biz/archives/202 vector和built-in数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此它能非常好的支持随即存取,即 ...

  5. Myeclipse 安装svn插件

    安装subclipse,  SVN插件1.从官网下载site-1.8.22.zip文件  访问不了可点我网盘2.从中解压出features与 plugins文件夹,复制到MyEclipse\MyEcl ...

  6. Maximum sum(poj 2479)

    题意:给一段数列,将这个数列分成两部分,使两部分的最大子段和的和最大,输出和 /* 看数据没想到是(O)n的算法,求出从前向后的最大子段和和从后向前的最大子段和, 然后枚举断点. 第一次提交不小心折在 ...

  7. Linux设置IP

    进入 vi /etc/sysconfig/network-scripts/ifcfg-eth0  root # ifconfig eth0 192.168.22.232 root # route ad ...

  8. p168习题

  9. 分布式系统唯一ID生成方案汇总

    系统唯一ID是我们在设计一个系统的时候常常会遇见的问题,也常常为这个问题而纠结.生成ID的方法有很多,适应不同的场景.需求以及性能要求.所以有些比较复杂的系统会有多个ID生成的策略.下面就介绍一些常见 ...

  10. 如何使用Linux的Crontab定时执行PHP脚本的方法

    我们的PHP程序有时候需要定时执行,我们可以使用ignore_user_abort函数或是在页面放置js让用户帮我们实现.但这两种方法都不太可靠,不稳定.我们可以借助Linux的Crontab工具来稳 ...