[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]最小矩形覆盖 凸包+旋转卡壳
题目大意 用最小矩形覆盖平面上所有的点 分析 有一结论:最小矩形中有一条边在凸包的边上,不然可以旋转一个角度让面积变小 简略证明 我们逆时针枚举一条边 用旋转卡壳维护此时最左,最右,最上的点 注意 注 ...
随机推荐
- windows环境下,apache虚拟主机配置
在windows环境下,apache从配置文件的相关配置: Windows 是市场占有率最高的 PC 操作系统, 也是很多人的开发环境. 其 VirtualHost 配置方法与 Linux 上有些差异 ...
- Beta Scrum Day 3
听说
- 学号:201621123032 《Java程序设计》第9周学习总结(
1:本周学习总结 1.1:以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容 2:书面作业 2.1: List中指定元素的删除(题集题目) 2.1.1:实验总结.并回答:列举至少2种在List ...
- 第九条:覆盖equals方法时总要覆盖hashCode方法
Object类的hashCode方法: public native int hashCode(); 是一个本地方法. 其中这个方法的主要注释如下: Whenever it is invoked o ...
- 服务器磁盘阵列数据恢复,raid5两块硬盘掉线数据恢复方法
[用户单位信息] 农业科学研究院某研究所 [磁盘阵列故障发生过程描述]客户的DELL MD1000服务器内置15块1TB硬盘搭建为RAID5磁盘阵列阵列,服务器在正常工作中有一块硬盘离线,管理员对磁盘 ...
- 双击CAD对象(具有扩展数据),显示自定义对话框实现方法
转自:Cad人生 链接:http://www.cnblogs.com/cadlife/p/3463337.html 题目:双击CAD对象,显示自定义对话框实现方法 内容粘贴如下: 主要是绑定两个事件: ...
- JAVA_SE基础——35.static修饰成员函数
在Java中适用static关键字修饰的方法称为静态方法. 声明静态方法的语法格式如下: 权限修饰符 static 数据类型 方法名(){ 方法体 } 静态方法 可以使用类名直接调用 类名.方 ...
- python入门(9)字符串和编码
python入门(9)字符串和编码 字符串是一种数据类型,比较特殊的是字符串有一个编码问题. 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理. 最早的计算机在设计时采用8个比 ...
- django的models模型类的常用数据类型和选项
django框架的models模块ORM框架,能够让我们通过编写类的方式,帮助我们自动生成数据库表. 生成的数据库表名为 应用模块名称_类名 数据库表中字段名 如果我们没有在参数中指定,就是我们写的类 ...
- pthon/零起点(一、集合)
pthon/零起点(一.集合) set( )集合,集合是无序的,集合是可变的,集合是可迭代的 set()强型转成集合数据类型 set()集合本身就是去掉重复的元素 集合更新操作案列: j={1,2,3 ...