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 ...
随机推荐
- golang代码执行顺序
一:首先man.go,整个程序的入口 func main() { beego.Run() } 然后beego.run()代码 // Run beego application. // beego.Ru ...
- Oracle一个用户查询另一个用户的表数据
1.两个用户是在不同的库,需要建立dblink 2.属于同一个库的不同用户 1)方法一:使用"用户名."的方式访问 例如:要从USER1账号访问USER2中的表TABLE2 A. ...
- centos 解压rar文件
默认情况下centos是不支持winrar的解压与打包的,需要安装winrar的linux版本程序 首先得下载解压软件 wget http://www.rarsoft.com/rar/rarlinux ...
- Java Garbage Collection/垃圾收集 策略查看
Java 的垃圾收集有各种各样的策略,默认的策略也会经常的改变. --比如到底是 serial , parallel, CMS; 具体到 Minor 怎么样,Old 又怎么样? 命令 java -XX ...
- 使用 Subversion (SVN) 的方式来访问 Github(转)
[转至]:http://www.open-open.com/lib/view/open1340760267717.html
- libCEF总结02字符串
libCEF 的 CefString.cef_string_t 在 Windows 下均表示一个 16 位的 Unicode 字符串,它们的使用请参考下面的代码 {//wchar_t* ==> ...
- DSP算法学习-过采样技术
DSP算法学习-过采样技术 彭会锋 2015-04-27 23:23:47 参考论文: 1 http://wr.lib.tsinghua.edu.cn/sites/default/files/1207 ...
- Qt Charts
简述 Qt Charts模块提供了一套易于使用的图表组件.它采用了Qt Graphics View框架,因此图表可以很容易地集成到现代的用户界面. Qt Charts可以被用作QWidgets.QGr ...
- hdu----(1847)Good Luck in CET-4 Everybody!(简单巴什博奕)
Good Luck in CET-4 Everybody! Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K ...
- Java script基础
Java script基础 Js的每个语句后面都要有分号. <script type="text/java script">所有JS内容</script> ...