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 ...
随机推荐
- (转)Thread.setDaemon设置说明
本想搜下python多线程里的setDaemon,发现了这篇文章写得很不错:http://blog.csdn.net/m13666368773/article/details/7245570 Thre ...
- 转:UML类图几种关系的总结
转自:http://www.open-open.com/lib/view/open1328059700311.html 在UML类图中,常见的有以下几种关系: 泛化(Generalization), ...
- Css_加载样式
第一种效果: 代码如下: <div class="loading"> <span></span> <span></span&g ...
- java 嵌套类 简记
嵌套类包括:1)静态嵌套类 (static 修饰符) 2)非静态嵌套类(又叫内部类) 其中内部类又可分为三种: 其一.在一个类(外部类)中直接定义的内部类: 其二.在一个方法(外部类的方法)中定义的 ...
- Laravel多对多简析
首先生成两张数据表,一般要实现两张数据表之间的联系要建立第三张表,如下 数据表生成之后,生成一些测试数据,接下来就对表article_tag表进行操作 在模型文件中声明两张表之间的关系: 测试数据:
- Epplus使用教程1(基本介绍)
1.前言 目前Epplus的介绍中文资料很少,我也一直在摸索中使用它,以下是我在使用过程中得到的经验,写出来供大家参考.本系列共4章: 导出Excel之Epplus使用教程1(基本介绍) 导出Exce ...
- 【CITE】C#默认以管理员身份运行程序实现代码
//用于一种情况:C#软件打包后,在读写C盘文件时,会出现权限问题.使用管理员身份才可以运行 using System; using System.Collections.Generic; using ...
- 转 http://www.5icool.org/a/201106/a654.html CSS开发中常用的公用样式
overflow:hidden 隐藏溢出 一.自己总结的公用样式解析 html, body, div, p, ul, li, dl, dt, dd, h1, h2, h3, h4, h5, h6, f ...
- Qt之QSS(白色靓丽)
简述 Qt助手中有关于各种部件的QSS详细讲解,资源很丰富,请参考:Qt Style Sheets Examples. 白色靓丽 - 一款漂亮的QSS风格. 你可以直接使用,也可以随意转载,但请务必保 ...
- 解析 MACH_O 文件
现在做iOS开发的挺多,了解一下在苹果平台上程序运行的原理 解析 MACH_O 文件 这篇文章描述了如何解析 Mach-O 文件并稍微解释了一下它的格式.这不是一份权威指南,不过当你不知从何开始时,它 ...