[BZOJ1185][HNOI2007]最小矩形覆盖-[凸包+旋转卡壳]
Description
Solution
感性理解一下,最小矩形一定是由一条边和凸包上的边重合的。
然后它就是模板题了。。然而真的好难调,小于大于动不动就打错。
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const double eps=1e-;
int n;
struct node{double x,y;
friend node operator +(node a,node b){return node{a.x+b.x,a.y+b.y};}
friend node operator -(node a,node b){return node{a.x-b.x,a.y-b.y};}
friend double operator *(node a,node b){return a.x*b.y-a.y*b.x;}
friend double operator /(node a,node b){return a.x*b.x+a.y*b.y;}
friend node operator *(node a,double b) {return node{a.x*b,a.y*b};}
friend bool operator <(node a,node b) { return fabs(a.y-b.y)<eps?a.x<b.x:a.y<b.y;}
}p[],st[],low;
double dis(node a){return a.x*a.x+a.y*a.y;}
bool cmp(node a,node b){
double t=(a-p[])*(b-p[]);
if (fabs(t)<eps) return dis(a-p[])<dis(b-p[]);
return t>;
}
int top=,now;
int main()
{
scanf("%d",&n);
low.x=low.y=;
scanf("%lf%lf",&p[].x,&p[].y);
for (int i=;i<=n;i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
if (p[i]<p[]) swap(p[i],p[]);
}
sort(p+,p+n+,cmp);
st[++top]=p[];
for (int i=;i<=n;i++)
{
while (top>&&(st[top]-st[top-])*(p[i]-st[top])<eps) top--;
st[++top]=p[i];
}
st[]=st[top];
node pr[];
double L,R,D,H,ans=1e10;int l=,r=,now=;
for (int i=;i<top;i++)
{
D=sqrt(dis(st[i]-st[i+]));
while ((st[i+]-st[i])*(st[now+]-st[i])>(st[i+]-st[i])*(st[now]-st[i])-eps) now=(now+)%top;
while ((st[i+]-st[i])/(st[r+]-st[i])>(st[i+]-st[i])/(st[r]-st[i])-eps) r=(r+)%top;
if (!i) l=r;
while ((st[i+]-st[i])/(st[l+]-st[i])<(st[i+]-st[i])/(st[l]-st[i])+eps) l=(l+)%top;
L=(st[i+]-st[i])/(st[l]-st[i])/D;R=(st[i+]-st[i])/(st[r]-st[i])/D;
H=abs((st[i+]-st[i])*(st[now]-st[i])/D);
if ((R-L)*H<ans)
{
ans=(R-L)*H;
pr[]=st[i]+(st[i+]-st[i])*(R/D);
pr[]=pr[]+(st[r]-pr[])*(H/sqrt(dis(pr[]-st[r])));
pr[]=pr[]-(pr[]-st[i])*((R-L)/sqrt(dis(st[i]-pr[])));
pr[]=pr[]-(pr[]-pr[]);
}
}
now=;
for (int i=;i<=;i++) if (pr[i]<pr[now]) now=i;
printf("%.5f\n",ans);
for (int i=;i<=;i++)
{
if (pr[(i+now)%].x>-*1e-) pr[(i+now)%].x=fabs(pr[(i+now)%].x);
if (pr[(i+now)%].y>-*1e-) pr[(i+now)%].y=fabs(pr[(i+now)%].y);
printf("%.5f %.5f\n",pr[(i+now)%].x,pr[(i+now)%].y);
}
}
[BZOJ1185][HNOI2007]最小矩形覆盖-[凸包+旋转卡壳]的更多相关文章
- BZOJ1185[HNOI2007] 最小矩形覆盖(旋转卡壳)
BZOJ1185[HNOI2007] 最小矩形覆盖 题面 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形,输出所求矩形的面积和四个顶点的坐标 分析 首先可以先求凸包,因为覆盖了凸包上的顶点,凸 ...
- BZOJ1185 [HNOI2007]最小矩形覆盖 【旋转卡壳】
题目链接 BZOJ1185 题解 最小矩形一定有一条边在凸包上,枚举这条边,然后旋转卡壳维护另外三个端点即可 计算几何细节极多 维护另外三个端点尽量不在这条边上,意味着左端点尽量靠后,右端点尽量靠前, ...
- bzoj 1185 [HNOI2007]最小矩形覆盖 凸包+旋转卡壳
题目大意 用最小矩形覆盖平面上所有的点 分析 有一结论:最小矩形中有一条边在凸包的边上,不然可以旋转一个角度让面积变小 简略证明 我们逆时针枚举一条边 用旋转卡壳维护此时最左,最右,最上的点 注意 注 ...
- 2018.10.18 bzoj1185: [HNOI2007]最小矩形覆盖(旋转卡壳)
传送门 不难看出最后的矩形一定有一条边与凸包某条边重合. 因此先求出凸包,然后旋转卡壳求出当前最小矩形面积更新答案. 代码: #include<bits/stdc++.h> #define ...
- [HNOI2007][BZOJ1185] 最小矩形覆盖 [凸包+旋转卡壳]
题面 BZOJ题面 前置芝士 建议先学习向量相关的计算几何基础 计算几何基础戳这里 思路 用这道题学习一下凸包和旋转卡壳 首先是凸包部分 凸包 求凸包用的算法是graham算法 算法流程如下: 找到$ ...
- BZOJ1185 HNOI2007 最小矩形覆盖 凸包、旋转卡壳
传送门 首先,肯定只有凸包上的点会限制这个矩形,所以建立凸包. 然后可以知道,矩形上一定有一条边与凸包上的边重合,否则可以转一下使得它重合,答案会更小. 于是沿着凸包枚举这一条边,通过旋转卡壳找到离这 ...
- bzoj1185 [HNOI2007]最小矩形覆盖 旋转卡壳求凸包
[HNOI2007]最小矩形覆盖 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 2081 Solved: 920 ...
- BZOJ1185 : [HNOI2007]最小矩形覆盖
求出凸包后,矩形的一条边一定与凸包的某条边重合. 枚举每条边,求出离它最远的点和离它最左最右的点,因为那三个点是单调变化的,所以复杂度为$O(n)$. 注意精度. #include<cstdio ...
- bzoj千题计划209:bzoj1185: [HNOI2007]最小矩形覆盖
http://www.lydsy.com/JudgeOnline/problem.php?id=1185 题解去看它 http://www.cnblogs.com/TheRoadToTheGold/p ...
随机推荐
- window下安装好postgreSQL 9.3用cmd命令进入数据库(搞的我这个菜鸟只剩半条命)
linux下基本没什么问题,但在window操作系统下比较麻烦. 需要添加环境变量path路径:C:\Program Files (x86)\PostgreSQL\9.3\bin 添加postgres ...
- 揭秘:C++编译器的函数编译流程
http://www.cnblogs.com/zhenjing/archive/2010/10/20/1856309.html C++中的类型查找过程相对简单,基本上就是名字查找,这里不再介绍. 对于 ...
- Linux环境编程之IPC进程间通信(五):Posix消息队列1
对于管道和FIFO来说.必须应该先有读取者存在.否则先有写入者是没有意义的. 而消息队列则不同,它是一个消息链表,有足够写权限的线程可往别的队列中放置消息,有足够读权限的线程可从队列中取走消息.每一个 ...
- 2019.3.5 控制台输出log4j得有些报错信息
报错内容如下 log4j:WARN No appenders could be found for logger (org.springframework.test.context.junit4.Sp ...
- Monkeyrunner测试小实践
环境搭建完成后,我们通过命令打开模拟器,前提是在Eclipse中创建了一个模拟器 (1)cmd命令:emulator -avd 模拟器名称 启动了模拟器,此时你就会看到一个安卓模拟器的弹出 (2)cm ...
- Java并发基础概念
Java并发基础概念 线程和进程 线程和进程都能实现并发,在java编程领域,线程是实现并发的主要方式 每个进程都有独立的运行环境,内存空间.进程的通信需要通过,pipline或者socket 线程共 ...
- SpringBoot实战(三)之使用RestFul Web服务
一.导入maven依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...
- Ubuntu安装PHP7
安装PHP7 Ubuntu 16.04官方源自带PHP7,所以可以直接使用apt-get来安装. (1)安装PHP7以及常用扩展. -fpm php7.-mysql php7.-common php7 ...
- 使用iptables和tc对端口限速
首先,我们来看一下tc,TC(Traffic Control)命令,是linux自带的告警流控命令.Linux操作系统中的流量控制器TC(Traffic Control)用于Linux内核的流量控制, ...
- cocos2d-x开发: 完善接口范例分离模块
在上一篇文章中,我阐述了一下为什么要做分离这种工作,这篇文章没什么重点,只是将上一次没有完善的工作做完.原本我想做到像Lua-tests那样子,能够一次完全显示所有的tests,然后选择要执行的tes ...