[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]最小矩形覆盖 凸包+旋转卡壳
题目大意 用最小矩形覆盖平面上所有的点 分析 有一结论:最小矩形中有一条边在凸包的边上,不然可以旋转一个角度让面积变小 简略证明 我们逆时针枚举一条边 用旋转卡壳维护此时最左,最右,最上的点 注意 注 ...
随机推荐
- servlet本质
首先我们先要知道servlet是什么,这有两种解释.一是目前大多数人所说的,一个实现了servlet接口的类就可以叫作servlet.二,servlet只是一个接口.那么看起来这两点都和servlet ...
- beta冲刺5
昨天的问题: 登陆页面的整合重新制作 各主机版本更迭 我的社团显示功能修改调整 主页的头部替换掉 +修复帖子无法显示内容的问题 +试着将邮箱等判定用正则表达式进行实时判定. 今天的完成: 主要是线下进 ...
- C语言第二次博客作业---分支结构 陈张鑫
一.PTA实验作业 题目1:计算分段函数[2] 本题目要求计算下列分段函数f(x)的值: 1.实验代码 int main(){double x,y; scanf("%lf",&am ...
- 2017-2018-1 Java演绎法 第二周 作业
团队任务:讨论Android上的游戏软件 参考现代软件工程 第一章 [概论]练习与讨论: 软件有很多种,也有各种分类办法,本次团队任务是讨论选取Android上的一个游戏软件,考虑到每位组员接触的游戏 ...
- 2017-2018-1 20155215 第九周 加分项 PWD命令的实现
1 学习pwd命令 Linux中用 pwd 命令来查看"当前工作目录"的完整路径. 简单得说,每当你在终端进行操作时,你都会有一个当前工作目录. 在不太确定当前位置时,就会使用pw ...
- Alpha冲刺No.5
一.站立式会议 在助教帮助下,优先解决404的问题,将demo移植到自己项目上. 进一步制作界面. 将已做好的内容,移植到手机做部分测试,能够在同一路由子网内登录数据库. 二.实际项目进展 已经解决了 ...
- scrapy 模拟登陆
import scrapy import urllib.request from scrapy.http import Request,FormRequest class LoginspdSpider ...
- python 操作SQLAlchemy
SQLAlchemy python链接 pymysql mysql+pymysql://<username>:<password>@<host>/<dbnam ...
- C# Unity游戏开发——Excel中的数据是如何到游戏中的 (四)2018.4.3更新
本帖是延续的:C# Unity游戏开发--Excel中的数据是如何到游戏中的 (三) 最近项目不算太忙,终于有时间更新博客了.关于数据处理这个主题前面的(一)(二)(三)基本上算是一个完整的静态数据处 ...
- 自己动手写CPU(基于FPGA与Verilog)
大三上学期开展了数字系统设计的课程,下学期便要求自己写一个单周期CPU和一个多周期CPU,既然要学,就记录一下学习的过程. CPU--中央处理器,顾名思义,是计算机中最重要的一部分,功能就是周而复始地 ...