[HNOI2007]最小矩形覆盖
题目描述
给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形,输出所求矩形的面积和四个顶点坐标
输入输出格式
输入格式:
第一行为一个整数n(3<=n<=50000),从第2至第n+1行每行有两个浮点数,表示一个顶点的x和y坐标,不用科学计数法
输出格式:
第一行为一个浮点数,表示所求矩形的面积(精确到小数点后5位),接下来4行每行表示一个顶点坐标,要求第一行为y坐标最小的顶点,其后按逆时针输出顶点坐标.如果用相同y坐标,先输出最小x坐标的顶点
输入输出样例
6
1.0 3.00000
1 4.00000
2.0000 1
3 0.0000
3.00000 6
6.0 3.0
18.00000
3.00000 0.00000
6.00000 3.00000
3.00000 6.00000
0.00000 3.00000
最小的覆盖矩形肯定有边在凸包上
先求出凸包,然后枚举凸包上的边为直线构造矩形
用单调栈求出离该直线最远的点,左边最远的点和右边最远的点
就可以算出矩形的四个点
有可能输出-0.0000,所以要特判
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long double ld;
struct point
{
ld x,y;
}p[],s[];
point ansp[];
ld eps=1e-,res,ans;
int n,top;
ld cross(point a,point b)
{
return a.x*b.y-b.x*a.y;
}
point operator *(point a,double b)
{
return (point){a.x*b,a.y*b};
}
point operator -(point a,point b)
{
return (point){a.x-b.x,a.y-b.y};
}
point operator +(point a,point b)
{
return (point){a.x+b.x,a.y+b.y};
}
ld dot(point a,point b)
{
return a.x*b.x+a.y*b.y;
}
ld dist(point a)
{
return sqrt(a.x*a.x+a.y*a.y);
}
int dcmp(ld x)
{
if (x<-eps) return -;
if (x>eps) return ;
return ;
}
bool cmp(point a,point b)
{
return (a.y<b.y)||(a.y==b.y&&a.x<b.x);
}
bool cmp2(point a,point b)
{
int t=dcmp(cross((p[]-a),(p[]-b)));
if (t==) return dist(p[]-a)<dist(p[]-b);
return t>;
}
bool cmp3(point a,point b)
{
return atan2(a.y-ansp[].y,a.x-ansp[].x)<atan2(b.y-ansp[].y,b.x-ansp[].x);
}
void graham()
{int i;
sort(p+,p+n+,cmp);
sort(p+,p+n+,cmp2);
s[++top]=p[];s[++top]=p[];
for (i=;i<=n;i++)
{
while (top>&&dcmp(cross((p[i]-s[top-]),(s[top]-s[top-])))>=) top--;
s[++top]=p[i];
}
}
void solve()
{int i;
int pos=,r=,l;
s[top+]=s[];
for (i=;i<=top;i++)
{
ld D=dist(s[i+]-s[i]);
while (dcmp(cross((s[i+]-s[i]),(s[pos+]-s[i]))-cross((s[i+]-s[i]),(s[pos]-s[i])))>) pos=pos%top+;
while (dcmp(dot(s[i+]-s[i],s[r+]-s[i])-dot(s[i+]-s[i],s[r]-s[i]))>=) r=r%top+;
if (i==) l=r;
while (dcmp(dot(s[i+]-s[i],s[l+]-s[i])-dot(s[i+]-s[i],s[l]-s[i]))<=) l=l%top+;
ld L=dot(s[l]-s[i],s[i+]-s[i])/D;
ld R=dot(s[i+]-s[i],s[r]-s[i])/D;
ld H=cross((s[i+]-s[i]),(s[pos]-s[i]))/D;
res=(R-L)*H;if (res<) res=-res;
if (dcmp(res-ans)<)
{
ans=res;
ansp[]=s[i]+(s[i+]-s[i])*(L/D);
ansp[]=s[i]+(s[i+]-s[i])*(R/D);
ansp[]=ansp[]+(s[l]-ansp[])*(H/dist(s[l]-ansp[]));
ansp[]=ansp[]+(s[r]-ansp[])*(H/dist(s[r]-ansp[]));
if (dcmp(ansp[].x)==) ansp[].x=fabs(ansp[].x);
if (dcmp(ansp[].y)==) ansp[].y=fabs(ansp[].y);
if (dcmp(ansp[].x)==) ansp[].x=fabs(ansp[].x);
if (dcmp(ansp[].y)==) ansp[].y=fabs(ansp[].y);
if (dcmp(ansp[].x)==) ansp[].x=fabs(ansp[].x);
if (dcmp(ansp[].y)==) ansp[].y=fabs(ansp[].y);
if (dcmp(ansp[].x)==) ansp[].x=fabs(ansp[].x);
if (dcmp(ansp[].y)==) ansp[].y=fabs(ansp[].y);
}
}
}
int main()
{int i;
cin>>n;
ans=2e9;
for (i=;i<=n;i++)
{
scanf("%Lf%Lf",&p[i].x,&p[i].y);
}
graham();
solve();
printf("%.5Lf\n",ans);
sort(ansp+,ansp+,cmp);
sort(ansp+,ansp+,cmp3);
for (i=;i<=;i++)
printf("%.5Lf %.5Lf\n",ansp[i].x,ansp[i].y);
}
[HNOI2007]最小矩形覆盖的更多相关文章
- 【旋转卡壳+凸包】BZOJ1185:[HNOI2007]最小矩形覆盖
1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 1945 Solve ...
- BZOJ:1185: [HNOI2007]最小矩形覆盖
1185: [HNOI2007]最小矩形覆盖 这计算几何……果然很烦…… 发现自己不会旋转卡壳,补了下,然后发现求凸包也不会…… 凸包:找一个最左下的点,其他点按照与它连边的夹角排序,然后维护一个栈用 ...
- BZOJ 1185: [HNOI2007]最小矩形覆盖 [旋转卡壳]
1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 1435 Solve ...
- 【BZOJ1185】[HNOI2007]最小矩形覆盖(凸包,旋转卡壳)
[BZOJ1185][HNOI2007]最小矩形覆盖(凸包,旋转卡壳) 题面 BZOJ 洛谷 题解 最小的矩形一定存在一条边在凸包上,那么枚举这条边,我们还差三个点,即距离当前边的最远点,以及做这条边 ...
- bzoj1185 [HNOI2007]最小矩形覆盖 旋转卡壳求凸包
[HNOI2007]最小矩形覆盖 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 2081 Solved: 920 ...
- 1185: [HNOI2007]最小矩形覆盖
1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 1426 Solve ...
- BZOJ1185[HNOI2007] 最小矩形覆盖(旋转卡壳)
BZOJ1185[HNOI2007] 最小矩形覆盖 题面 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形,输出所求矩形的面积和四个顶点的坐标 分析 首先可以先求凸包,因为覆盖了凸包上的顶点,凸 ...
- 洛谷 P3187 BZOJ 1185 [HNOI2007]最小矩形覆盖 (旋转卡壳)
题目链接: 洛谷 P3187 [HNOI2007]最小矩形覆盖 BZOJ 1185: [HNOI2007]最小矩形覆盖 Description 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形, ...
- LG3187 [HNOI2007]最小矩形覆盖
题意 题目描述 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形,输出所求矩形的面积和四个顶点坐标 输入输出格式 输入格式: 第一行为一个整数n(3<=n<=50000),从第2至第 ...
- bzoj 1185 [HNOI2007]最小矩形覆盖 凸包+旋转卡壳
题目大意 用最小矩形覆盖平面上所有的点 分析 有一结论:最小矩形中有一条边在凸包的边上,不然可以旋转一个角度让面积变小 简略证明 我们逆时针枚举一条边 用旋转卡壳维护此时最左,最右,最上的点 注意 注 ...
随机推荐
- JavaScript(第二十三天)【事件入门】
JavaScript事件是由访问Web页面的用户引起的一系列操作,例如:用户点击.当用户执行某些操作的时候,再去执行一系列代码. 一.事件介绍 事件一般是用于浏览器和用户操作进行交互.最早是IE和 ...
- 数据结构基础——指针及动态内存分配(malloc)
一.指针 C语言中的指针是一种数据类型,比如说我们用int *a;就定义了一个指针a,它指向一个int类型的数.但是这个指针是未初始化的,所以,一般的,我们都在创建指针时初始化它,以免出错,在还不吃的 ...
- 201621123057 《Java程序设计》第9周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 在上一周的总结上做了一点补充 1.2 选做:收集你认为有用的代码片段 2. 书面作业 本次作业题集集合 1. ...
- caffe使用ctrl-c不能保存模型
caffe使用Ctrl-c 不能保存模型: 是因为使用的是 tee输出日志 解决方法:kill -s SIGINT <proc_id> 或者使用 GLOG_log_dir=/path/to ...
- nyoj 复杂度
复杂度 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 for(i=1;i<=n;i++) for(j=i+1;j<=n;j++) for(k=j+1;k ...
- pdf解析与结构化提取
#PDF解析与结构化提取##PDF解析对于PDF文档,我们选择用PDFMiner对其进行解析,得到文本.###PDFMinerPDFMiner使用了一种称作lazy parsing的策略,只在需要的时 ...
- ASP.NET Web API编程——路由
路由过程大致分为三个阶段: 1)请求URI匹配已存在路由模板 2)选择控制器 3)选择操作 1匹配已存在的路由模板 路由模板 在WebApiConfig.Register方法中定义路由,例如模板默认生 ...
- java程序员最不愿意看到的十件事
0.遍历结果集并构造对象如果你是个时髦的开发者而不是专业人员,显然你从某篇博客中读过有开发者遇到Hibernate的“性能问题”,因而认为ORM都不好,觉得手动编码“明显更好”.喜欢的话你当然可以用 ...
- 安装 docker-compose
安装Docker-Compose之前,请先安装 python-pip,安装好pip之后,就可以安装Docker-Compose了. 一.检查是否已经安装 二.安装 docker-compose 1.安 ...
- javascript学习(4)异常处理 try-catch 和 onerror
一.try-catch 1.样例1 1.1.源代码 1.2.执行后 2.样例2 2.1.源代码 2.2.执行后 二.onerror 1.源代码 2.执行后