bzoj 1185 旋转卡壳 最小矩形覆盖
题目大意 就是求一个最小矩形覆盖,逆时针输出其上面的点
这里可以看出,那个最小的矩形覆盖必然有一条边经过其中凸包上的两个点,另外三条边必然至少经过其中一个点,而这样的每一个点逆时针走一遍都满足单调性
所以可以利用旋转卡壳的思想找到这样的三个点
以每一条边作为基础,循环n次得到n个这样的矩形,找到其中面积最小的即可
然后自己画画图,作出矩形对应的两条边的单位向量,那么这四个点就非常好求了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 50010
#define eps 1e-9
const double PI = acos(-1.0);
int n , top; int dcmp(double x)
{
if(fabs(x)<eps) return ;
return x<?-:;
} struct Point{
double x , y;
Point(double x= , double y=):x(x),y(y){}
void input(){scanf("%lf%lf" , &x , &y);}
void output(){printf("%.5f %.5f\n" , x , y);}
bool operator<(const Point &m)const{
return x<m.x||(x==m.x&&y<m.y);
}
}po[N] , rec[N] , p[]; typedef Point Vector; Vector operator+(Vector a , Vector b){return Vector(a.x+b.x , a.y+b.y);}
Vector operator-(Vector a , Vector b){return Vector(a.x-b.x , a.y-b.y);}
Vector operator*(Vector a , double b){return Vector(a.x*b , a.y*b);}
Vector operator/(Vector a , double b){return Vector(a.x/b , a.y/b);}
double operator*(Vector a , Vector b){return a.x*b.y-a.y*b.x;} double Dot(Vector a , Vector b){return a.x*b.x+a.y*b.y;}
double Len(Vector a){return sqrt(Dot(a,a));}
int Polxy()
{
sort(po , po+n);
rec[]=po[] , rec[]=po[];
top=;
for(int i= ; i<n ; i++){
while(top>=&&(rec[top-]-rec[top-])*(po[i]-rec[top-])<=)
top--;
rec[top++] = po[i];
}
int tmp=top;
for(int i=n- ; i>= ; i--){
while(top>=tmp&&(rec[top-]-rec[top-])*(po[i]-rec[top-])<=)
top--;
rec[top++] = po[i];
}
top--;
return top;
} Vector Normal(Vector a)
{
double l = Len(a);
return Vector(-a.y/l , a.x/l);
} double calCalip()
{
// for(int i=0 ; i<top ; i++) rec[i].output();
Point ch[];
ch[] = rec[] , ch[] = rec[];
int i1= , i2= , i3=;
double maxn = 1e18;
ch[] = rec[] , ch[] = rec[];
while(dcmp(fabs((rec[(i1+)%top]-ch[])*(ch[]-ch[]))-fabs((rec[i1]-ch[])*(ch[]-ch[])))>=) i1=(i1+)%top;
while(dcmp(Dot(rec[(i2+)%top]-ch[] , ch[]-ch[])-Dot(rec[i2]-ch[] , ch[]-ch[]))>=) i2=(i2+)%top;
while(dcmp(Dot(rec[(i3-+top)%top]-ch[] , ch[]-ch[])-Dot(rec[i3]-ch[] , ch[]-ch[]))>=) i3=(i3-+top)%top;
for(int i= ; i<top ; i++){
ch[] = rec[i] , ch[] = rec[(i+)%top];
while(dcmp(fabs((rec[(i1+)%top]-ch[])*(ch[]-ch[]))-fabs((rec[i1]-ch[])*(ch[]-ch[])))>=) i1=(i1+)%top;
while(dcmp(Dot(rec[(i2+)%top]-ch[] , ch[]-ch[])-Dot(rec[i2]-ch[] , ch[]-ch[]))>=) i2=(i2+)%top;
while(dcmp(Dot(rec[(i3+)%top]-ch[] , ch[]-ch[])-Dot(rec[i3]-ch[] , ch[]-ch[]))>=) i3=(i3+)%top;
double l = Len(ch[]-ch[]);
double h = fabs((rec[i1]-ch[])*(ch[]-ch[]))/l;
double len1 = Dot(rec[i2]-ch[] , ch[]-ch[])/l; //右侧长度
double len2 = Dot(rec[i3]-ch[] , ch[]-ch[])/l; //左侧长度
double suml = l+len1+len2;
// cout<<i<<" "<<l<<" "<<h<<" "<<len1<<" "<<len2<<" "<<suml*h<<endl;
if(dcmp(suml*h-maxn)<){
Vector unit1 = (ch[]-ch[])/l;
Vector unit2 = Normal(unit1);
maxn = suml*h;
p[] = ch[]+unit1*len1;
p[] = p[]+unit2*h;
p[] = p[]-unit1*suml;
p[] = p[]-unit2*h;
}
}
return maxn;
} int main()
{
// freopen("in.txt" , "r" , stdin);
while(scanf("%d" , &n)!=EOF)
{
for(int i= ; i<n ; i++) po[i].input();
Polxy();
double ret = calCalip();
printf("%.5f\n" , ret);
int st = ;
for(int i= ; i< ; i++){
if(p[i].y<p[st].y || (p[i].y==p[st].y&&p[i].x<p[st].x)) st = i;
}
for(int i=;i<;i++){
p[st].output();
st = (st+)%;
}
}
return ;
}
bzoj 1185 旋转卡壳 最小矩形覆盖的更多相关文章
- HDU 5251 矩形面积(二维凸包旋转卡壳最小矩形覆盖问题) --2015年百度之星程序设计大赛 - 初赛(1)
题目链接 题意:给出n个矩形,求能覆盖所有矩形的最小的矩形的面积. 题解:对所有点求凸包,然后旋转卡壳,对没一条边求该边的最左最右和最上的三个点. 利用叉积面积求高,利用点积的性质求最左右点和长度 ...
- 洛谷 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 ...
- bzoj 1185 [HNOI2007]最小矩形覆盖 凸包+旋转卡壳
题目大意 用最小矩形覆盖平面上所有的点 分析 有一结论:最小矩形中有一条边在凸包的边上,不然可以旋转一个角度让面积变小 简略证明 我们逆时针枚举一条边 用旋转卡壳维护此时最左,最右,最上的点 注意 注 ...
- 【旋转卡壳+凸包】BZOJ1185:[HNOI2007]最小矩形覆盖
1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 1945 Solve ...
- BZOJ:1185: [HNOI2007]最小矩形覆盖
1185: [HNOI2007]最小矩形覆盖 这计算几何……果然很烦…… 发现自己不会旋转卡壳,补了下,然后发现求凸包也不会…… 凸包:找一个最左下的点,其他点按照与它连边的夹角排序,然后维护一个栈用 ...
- 【BZOJ1185】[HNOI2007]最小矩形覆盖(凸包,旋转卡壳)
[BZOJ1185][HNOI2007]最小矩形覆盖(凸包,旋转卡壳) 题面 BZOJ 洛谷 题解 最小的矩形一定存在一条边在凸包上,那么枚举这条边,我们还差三个点,即距离当前边的最远点,以及做这条边 ...
- [hdu5251]矩形面积 旋转卡壳求最小矩形覆盖
旋转卡壳求最小矩形覆盖的模板题. 因为最小矩形必定与凸包的一条边平行,则枚举凸包的边,通过旋转卡壳的思想去找到其他3个点,构成矩形,求出最小面积即可. #include<cstdio> # ...
- bzoj1185 [HNOI2007]最小矩形覆盖 旋转卡壳求凸包
[HNOI2007]最小矩形覆盖 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 2081 Solved: 920 ...
随机推荐
- POJ 3468 线段树裸题
这些天一直在看线段树,因为临近期末,所以看得断断续续,弄得有些知识点没能理解得很透切,但我也知道不能钻牛角尖,所以配合着刷题来加深理解. 然后,这是线段树裸题,而且是最简单的区间增加与查询,我参考了A ...
- ps前端切图常用快捷键
一.新建文件:预设-自定:宽度1920,单位像素,高度自定义:分辨率:72像素/英寸:颜色模式:RGB,8位:背景色:透明:可存储预设,下次新建的时候,直接在预设中,选择那个名称,点确定.视图:显示- ...
- OpenGL的GLUT注册回调函数[转]
OpenGL的注册回调函数 void glutDisplayFunc(void (*func)(void) ); 为当前窗口设置显示回调函数 void glutOverlayDisplayFunc(v ...
- Mybatis调用Mysql存储过程
在我的后台系统中,今天需要使用到存储过程.存储过程还真没写过,今天就写了个存储过程.使用在后台中. 其实这个接口功能 是涉及几张表的修改,删除,新增的.就写个一个存储过程. 存储过程: ), ),) ...
- iOS开发 字符串MD5加密
/*** MD5 ***/ #define CC_MD5_DIGEST_LENGTH 16 /* digest length in bytes */ #define CC_MD ...
- phalcon: 视图集成(内嵌模板)
当一个网站把不同的模板分割成:头部,中间区域,底部时,我们就需要在不同的[中间区域]页面引入相同的头部跟底部.引入有2种方法, 一种是:在controller中调用: $this->view-& ...
- 腾讯云从零部署nodejs站点
版权声明:本文由袁飞翔原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/176 来源:腾云阁 https://www.qclo ...
- Shell基础:变量类型 & 运算符
Shell变量 Shell支持三种类型的变量 用户自定义变量:用户自定义的变量,变量名以英文字母或下划线开头,区分大小写. 位置变量:根据位置传递参数给脚本的变量,默认支持9个位置变量 $1,$2,$ ...
- poj------(3468)A Simple Problem with Integers(区间更新)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 60745 ...
- ARM流水线关键技术分析与代码优化
引 言 流水线技术通 过多个功能部件并行工作来缩短程序执行时间,提高处理器核的效率和吞吐率,从而成为微处理器设计中最为重要的技术之一.ARM7处理器核使用了典型三级流 水线的冯·诺伊曼结构,AR ...