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 ...
随机推荐
- hiho_1049 二叉树遍历
题目大意 给出一棵二叉树的前序和中序遍历结果,求出后序遍历的结果.保证二叉树中节点值均不相同. 分析 通过前序和中序遍历的结果,我们可以构建出二叉树,若构建出二叉树,则后序遍历的结果很容易求出(当然递 ...
- No resource found that matches the given name 'Theme.AppCompat.Light'
eclipse在新建andorid工程的时候出现找不到AppCompat.Light主题的问题,这是因为缺少支持低版本的v7包所致, 这个不是jar包,在sdk的extras->andorid- ...
- java 抽象类
抽象类: 1)函数没有方法体,就必须用abstract修饰. 2)抽象函数所在的类必须也是抽象的. 3)非抽象的类继承于抽象类,必须实现其全部方法. 4)抽象类中可以存在抽象方法,也可以不存在. 5) ...
- dede顶级栏目直接显示内容
点击网站栏目管理,增加顶级栏目 在弹出的增加窗口中,填上栏目名称,其它的如果没有特殊的要求可直接默认 点击常规选项旁边的高级选项,并且在列表模板中,将其改一个文件名,这个文件名就是后面需要使用到的文件 ...
- Unity5 新功能解析--物理渲染与standard shader
Unity5 新功能解析--物理渲染与standard shader http://blog.csdn.net/leonwei/article/details/48395061 物理渲染是UNITY5 ...
- tcp服务的测试程序开源
开源的是一个测试客户端,可以用来检验服务器端程序的并发处理能力. 使用方法为: python epolltest.py --host=192.168.15.128 --port=8809 --degr ...
- 你的java 代码对JIT编译友好吗?
JIT编译器是Java虚拟机(以下简称JVM)中效率最高并且最重要的组成部分之一.但是很多的程序并没有充分利用JIT的高性能优化能力,很多开发者甚至也并不清楚他们的程序有效利用JIT的程度. 在本文中 ...
- DSP基础学习-ADC同步采样
DSP基础学习-ADC同步采样 彭会锋 2015-04-28 20:31:06 在DSP28027 LauchPad学习过程中,关于ADC同步采样和顺序采样的区别稍加研究了一下,发现里面还真有些门道, ...
- python中urllib和urllib2的简单用法
import urllib #引入urllib模块,这里用urllib2也可以 fpage = urllib.urlopen( url ) #打开网页:例如url=‘http://www.xxx.co ...
- Python中一些内建函数及os等模块的用法
len(obj) # 求长度:obj可以是str.list等对象 split(str, num) # str-分割符,默认空格: ...