bzoj 1185 最小矩形覆盖 —— 旋转卡壳
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1185
枚举一条边,维护上、左、右方的点;
上方点到这条边距离最远,所以用叉积求面积维护;
左右点到这条边的射影最长(!),所以用点积求射影维护;
因为维护的点是只能逆时针走的,所以初始的左边点要特殊处理一下,其实等于右边点即可,然后可以走过去到合适位置;
然后维护矩形的四个端点,就是根据距离,从边的端点走过去,还挺有意思的;
注意不要输出 -0;
然而这其实是假的呵呵,Narh 一拍就出错了,还是很小的数据很明显的错囧
只是不知道哪里错,怎么调...
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double db;
db const eps=1e-;
int const xn=;
int n;
db ans;
int dmp(db x){if(fabs(x)<=eps)return ; return x>eps?:-;}
struct P{
db x,y;
P(db x=,db y=):x(x),y(y) {}
bool operator < (const P &b) const
{return dmp(x-b.x)<||dmp(x-b.x)==&&dmp(y-b.y)<;}
P operator + (const P &b) const
{return P(x+b.x,y+b.y);}
P operator - (const P &b) const
{return P(x-b.x,y-b.y);}
P operator * (const db &v) const
{return P(x*v,y*v);}
P operator / (const db &v) const
{return P(x/v,y/v);}
}p[xn],c[xn],pos[];
db cross(P a,P b){return a.x*b.y-a.y*b.x;}
db dot(P a,P b){return a.x*b.x+a.y*b.y;}
void find()
{
sort(p+,p+n+); int top=;
for(int i=;i<=n;i++)
{
while(top>&&dmp(cross(c[top]-c[top-],p[i]-c[top]))<=)top--;
c[++top]=p[i];
}
int num=top;
for(int i=n-;i;i--)
{
while(top>num&&dmp(cross(c[top]-c[top-],p[i]-c[top]))<=)top--;
c[++top]=p[i];
}
n=top-;
}
int upt(int x){if(x>n)x-=n; if(x<)x+=n; return x;}
db sqr(db x){return x*x;}
db dis(P a,P b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
bool cmp(P a,P b){return dmp(a.y-b.y)<||(dmp(a.y-b.y)==&&dmp(a.x-b.x)<);}
void rc()
{
ans=-;
//int p=2,l=1,r=2;//
int p=,l=,r=; c[n+]=c[];
for(int i=;i<=n;i++)
{
db d=dis(c[i],c[i+]);
while(dmp(cross(c[i]-c[p],c[i+]-c[p])-cross(c[i]-c[p+],c[i+]-c[p+]))<=)p=upt(p+);
while(dmp(dot(c[r]-c[i],c[i+]-c[i])-dot(c[r+]-c[i],c[i+]-c[i]))<=)r=upt(r+);
if(i==)l=r;//
while(dmp(dot(c[l]-c[i],c[i+]-c[i])-dot(c[l+]-c[i],c[i+]-c[i]))>=)l=upt(l+);
db L=dot(c[i+]-c[i],c[l]-c[i])/d;
db R=dot(c[i+]-c[i],c[r]-c[i])/d;
db H=cross(c[i]-c[p],c[i+]-c[p])/d;
db tmp=(R-L)*H;
if(ans<||dmp(ans-tmp)>)
{
ans=tmp;
pos[]=c[i]+(c[i+]-c[i])*(R/d);
pos[]=pos[]+(c[r]-pos[])*(H/dis(c[r],pos[]));
//pos[2]=pos[1]+(c[p]-pos[1])*((R-L)/dis(c[p],pos[1]));//也可
pos[]=pos[]+(c[i]-pos[])*((R-L)/dis(c[i],pos[]));
pos[]=pos[]+(pos[]-pos[]);
}
}
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
find();
rc();
printf("%.5f\n",ans);
int st=;
for(int i=;i<;i++)if(cmp(pos[i],pos[st]))st=i;
for(int i=st,cnt=;cnt<=;i=(i+)%,cnt++)
{
if(fabs(pos[i].x)<=eps)pos[i].x=;
if(fabs(pos[i].y)<=eps)pos[i].y=;
printf("%.5f %.5f\n",pos[i].x,pos[i].y);
}
return ;
}
bzoj 1185 最小矩形覆盖 —— 旋转卡壳的更多相关文章
- 洛谷 P3187 BZOJ 1185 [HNOI2007]最小矩形覆盖 (旋转卡壳)
题目链接: 洛谷 P3187 [HNOI2007]最小矩形覆盖 BZOJ 1185: [HNOI2007]最小矩形覆盖 Description 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形, ...
- BZOJ 1185: [HNOI2007]最小矩形覆盖 [旋转卡壳]
1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 1435 Solve ...
- bzoj1185 [HNOI2007]最小矩形覆盖 旋转卡壳求凸包
[HNOI2007]最小矩形覆盖 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 2081 Solved: 920 ...
- bzoj 1185 [HNOI2007]最小矩形覆盖——旋转卡壳
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1185 矩形一定贴着凸包的一条边.不过只是感觉这样. 枚举一条边,对面的点就是正常的旋转卡壳. ...
- BZOJ 1185: [HNOI2007]最小矩形覆盖-旋转卡壳法求点集最小外接矩形(面积)并输出四个顶点坐标-备忘板子
来源:旋转卡壳法求点集最小外接矩形(面积)并输出四个顶点坐标 BZOJ又崩了,直接贴一下人家的代码. 代码: #include"stdio.h" #include"str ...
- 【bzoj1185】[HNOI2007]最小矩形覆盖 (旋转卡壳)
给你一些点,让你用最小的矩形覆盖这些点 首先有一个结论,矩形的一条边一定在凸包上!!! 枚举凸包上的边 用旋转卡壳在凸包上找矩形另外三点... 注意精度问题 #include<cstdio> ...
- BZOJ 1185 最小矩形覆盖
Description Input Output Sample Input Sample Output HINT 其实这题就是一道旋转卡壳的裸题,但是我的精度萎了.直接上hzwer的代码吧... #i ...
- HDU 5251 矩形面积 (旋转卡壳)
2015年百度之星程序设计大赛 - 初赛(1) 1006 比赛链接:2015年百度之星程序设计大赛 - 初赛(1) 题目链接:HDU 5251 Problem Description 小度熊有一个桌面 ...
- bzoj 1185 [HNOI2007]最小矩形覆盖 凸包+旋转卡壳
题目大意 用最小矩形覆盖平面上所有的点 分析 有一结论:最小矩形中有一条边在凸包的边上,不然可以旋转一个角度让面积变小 简略证明 我们逆时针枚举一条边 用旋转卡壳维护此时最左,最右,最上的点 注意 注 ...
随机推荐
- 第一课 第一个nodejs程序
这就是我们的第一个程序了 在控制台会输出:hello 我们需要运行该文件 开始->运行 cmd 进入我们的程序目录 我的是D:/nodejs/hello.js 进入程序目录cd D:/nodej ...
- spring属性注入方式
一.使用有参构造注入属性 配置文件 constructor-arg标签是需注入属性的名字 User类 生成了User的有参构造函数 测试类 结果 打印出了name属性的值 二.使用set方法注入属性 ...
- Android动画效果animation
1.Tween 根据指定动画开始和结束时的对象属性(位置.Alpha值(透明度).大小.角度等)以及动画播放的时间长度生成动画: 2.Frame 指定每一帧所播放的图片和时间长度. 建立动画的方法 ...
- Apache Shiro 使用手册(二)Shiro 认证(转发:http://kdboy.iteye.com/blog/1154652)
认证就是验证用户身份的过程.在认证过程中,用户需要提交实体信息(Principals)和凭据信息(Credentials)以检验用户是否合法.最常见的“实体/凭证”组合便是“用户名/密码”组合. 一. ...
- linux 如何查找命令的路径
linux 下,我们常使用 cd ,grep,vi 等命令,有时候我们要查到这些命令所在的位置,如何做呢? linux下有2个命令可完成该功能:which ,whereis which 用来查看当 前 ...
- HDU - 1272 小希的迷宫 【并查集】
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1272 思路 只需要判断 这张图 无环 并且只有一个连通块 就可以了 要注意 如果 只输入 0 0 那给 ...
- 【leetcode刷题笔记】Reverse Words in a String
Given an input string, reverse the string word by word. For example,Given s = "the sky is blue& ...
- 【六】MongoDB管理之副本集
一.复制介绍 所谓的复制就是在多个主机之间同步数据的过程. 1.数据冗余及可用性 复制技术提供数据冗余及可用性,在不同的数据库服务器上使用多个数据副本,复制技术防止单个数据库服务器出现数据故障而出现数 ...
- crontab 定时器
cronntab 定时器 crontab -e 编辑定时器 crontab -l 查看定时器 //每十分钟执行一次 */10 * * * * curl http://xxxxx //每天 凌晨 中午1 ...
- tornado源码分析
初识tornado 首先从经典的helloword案例入手 import tornado.ioloop import tornado.web class MainHandler(tornado.web ...