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 ...
随机推荐
- ACM比赛经验
这篇博客是转别人的,觉得很好,希望能在以后的现场赛中用上:ACM比赛经验 推荐此篇文章打印,与模板放在一起. 1. 比赛中评测会有些慢,偶尔还会碰到隔10分钟以上才返回结果的情况,这段时间不能等结果, ...
- 【服务器环境搭建-Centos】系统分区 待续
df命令查看,显示/dev/vda,而不是sda或hda ,为什么? 虚拟机为了提升性能,一般使用virtio作为磁盘驱动,在虚拟机里面磁盘会显示成vda而不是传统的sda,有什么办法可以让他显示成s ...
- VC++源文件编码
目录 第1章源代码文件 1 1.1 研究思路 1 1.2 实验结果 3 1.3 #pragma setlocale 4 1.4 /source-charset 5 1.5 ...
- Eclipse中Ant的配置与测试 转
欢迎关注我的社交账号: 博客园地址: http://www.cnblogs.com/jiangxinnju/p/4781259.html GitHub地址: https://github.com/ji ...
- jmeter笔记8
JMETER接口性能测试方案 JMETER简介 JMeter可以用于测试静态或者动态资源的性能(文件.Servlets.Perl脚本.java对象.数据库和查询.ftp服务器或者其 ...
- .NET Reflector 8.2支持VS2013高亮显示和代码地图视图
Red Gate Software公司最近发布的.NET Reflector 8.2支持Visual Studio 2013,其Reflector 桌面程序能够转换十六进制/十进制值.桌面程序还支持局 ...
- [Spring] spring-session + JedisPool 实现 session 共享
1.至少导入四个jar包: jedis spring-session spring-data-redis commons-pool2 2.bean配置 <?xml version="1 ...
- postgresql 触发器
一.创建事件触发器 1.ddl_command_start - 一个DDL开始执行前被触发: 2.ddl_command_end - 一个DLL 执行完成后被触发: 3.sql_drop -- 删除一 ...
- uva----(100)The 3n + 1 problem
The 3n + 1 problem Background Problems in Computer Science are often classified as belonging to a ...
- 批量Load/Store指令的寻址方式
批量Load/Store指令用于实现在一组寄存器和一块连续的内存单元之间传输数据.也称为多寄存器寻址方式,即一条指令可以完成多个寄存器值的传送.这种寻址方式可以用一条指令最多完成传送16个通用寄存器的 ...