BZOJ 1185: [HNOI2007]最小矩形覆盖-旋转卡壳法求点集最小外接矩形(面积)并输出四个顶点坐标-备忘板子
来源:旋转卡壳法求点集最小外接矩形(面积)并输出四个顶点坐标
BZOJ又崩了,直接贴一下人家的代码。
代码:
#include"stdio.h"
#include"string.h"
#include"math.h"
#define M 50006
#define eps 1e-10
#include"stdlib.h"
#define inf 999999999
typedef struct node
{
double x,y,dis,cos;
}P;
P p[M],q[M],pp[M];
double min(double a,double b)
{
return a<b?a:b;
}
int cmp(const void *a,const void *b)
{
if(fabs((*(struct node*)a).cos-(*(struct node*)b).cos)<eps)
return (*(struct node*)a).dis>(*(struct node*)b).dis?:-;
else
return (*(struct node*)b).cos>(*(struct node*)a).cos?:-; }
double pow(double x)
{
return x*x;
}
double Len(node p0,node p1)
{
return pow(p1.x-p0.x)+pow(p1.y-p0.y);
}
double COS(node p0,node p1)
{
double x1=p1.x-p0.x;
double y1=p1.y-p0.y;
double x2=;
double y2=;
return (x1*x2+y1*y2)/sqrt((x1*x1+y1*y1)*(x2*x2+y2*y2));
}
double cross(node p0,node p1,node p2)
{
double x1=p1.x-p0.x;
double y1=p1.y-p0.y;
double x2=p2.x-p0.x;
double y2=p2.y-p0.y;
return x1*y2-x2*y1;
}
double dot(node p0,node p1,node p2)
{
double x1=p1.x-p0.x;
double y1=p1.y-p0.y;
double x2=p2.x-p1.x;
double y2=p2.y-p1.y;
return x1*x2+y1*y2;
}
node miss(node q1,double a,double b,node q2)//求两直线交点坐标
{
node ret;
double c1=a*q1.y-b*q1.x;
double c2=-a*q2.x-b*q2.y;
ret.x=-(b*c1+a*c2)/(a*a+b*b);
ret.y=(a*c1-b*c2)/(a*a+b*b);
return ret;
}
int main()
{
int n,i,j;
while(scanf("%d",&n)!=-)
{
node start;
int tep;
start.x=start.y=inf;
for(i=;i<n;i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
if(start.y>p[i].y)
{
start=p[i];
tep=i;
}
else if(fabs(start.y-p[i].y)<eps)
{
if(start.x>p[i].x)
{
start=p[i];
tep=i;
}
}
}
p[tep].dis=;
p[tep].cos=1.0;
for(i=;i<n;i++)
{
if(i!=tep)
{
if(fabs(p[i].x-start.x)<eps&&fabs(p[i].y-start.y)<eps)
{
p[i].dis=;
p[i].cos=1.0;
}
else
{
p[i].dis=Len(start,p[i]);
p[i].cos=COS(start,p[i]);
}
}
}
qsort(p,n,sizeof(p[]),cmp);
int tt=;
for(i=;i<n;i++)
{
if(fabs(p[i].cos-p[(i+)%n].cos)>eps||fabs(p[i].dis-p[(i+)%n].dis)>eps)
pp[tt++]=p[i];
}
if(tt==)
{
printf("%.5lf\n",0.0);
for(i=;i<;i++)
printf("%.5lf %.5lf\n",p[].x,p[].y);
continue;
}
int flag=;
for(i=;i<tt-;i++)
{
if(fabs(p[i].cos-p[i+].cos)>eps)
flag++;
}
if(!flag)
{
printf("%.5lf\n",0.0);
printf("%.5lf %.5lf\n",pp[].x,pp[].y);
printf("%.5lf %.5lf\n",pp[tt-].x,pp[tt-].y);
printf("%.5lf %.5lf\n",pp[tt-].x,pp[tt-].y);
printf("%.5lf %.5lf\n",pp[].x,pp[].y);
continue;
}
q[]=pp[tt-];//注意tt;
q[]=pp[];
q[]=pp[];
int cnt=;
for(i=;i<tt;i++)
{
while(cross(q[cnt-],q[cnt],pp[i])<)
{
cnt--;
}
q[++cnt]=pp[i];
}
int k1,k2;
k1=;
j=;
double S=inf;
double a[],b[];
int indx[];
for(i=;i<cnt;i++)
{
double w=sqrt(Len(q[i],q[(i+)%cnt]));
while(cross(q[i],q[(i+)%cnt],q[(j+)%cnt])>cross(q[i],q[(i+)%cnt],q[j%cnt]))
{
j++;
}
double high=cross(q[i],q[(i+)%cnt],q[j%cnt])/w;
while(dot(q[i],q[(i+)%cnt],q[(k1+)%cnt])>dot(q[i],q[(i+)%cnt],q[(k1)%cnt]))
{
k1++;
}
if(i==)
k2=k1;
while(dot(q[i],q[(i+)%cnt],q[(k2+)%cnt])<=dot(q[i],q[(i+)%cnt],q[(k2)%cnt]))
{
k2++;
}
double wide=(dot(q[i],q[(i+)%cnt],q[(k1)%cnt])-dot(q[i],q[(i+)%cnt],q[(k2)%cnt]))/w;
if(S>high*wide)
{
S=high*wide;//更新四个切点坐标以及旋转的直线的方向向量
indx[]=i;
indx[]=k1%cnt;
indx[]=j%cnt;
indx[]=k2%cnt;
a[]=q[(i+)%cnt].x-q[i].x;
b[]=q[(i+)%cnt].y-q[i].y;
a[]=b[];
b[]=-a[];
a[]=a[];
b[]=b[];
a[]=b[];
b[]=-a[];
}
}
printf("%.5lf\n",S);
node ret[];
start.x=start.y=inf; for(i=;i<;i++)//先找出左下角的点的坐标然后按照极角排序
{
ret[i]=miss(q[indx[i]],a[i],b[i],q[indx[(i+)%]]);
//printf("%.5lf %.5lf\n",ret[i].x,ret[i].y);
if(start.y>ret[i].y)
{
start=ret[i];
tep=i;
}
else if(fabs(start.y-ret[i].y)<eps)
{
if(start.x>ret[i].x)
{
start=ret[i];
tep=i;
} }
}
ret[tep].dis=;
ret[tep].cos=1.5;
for(i=;i<;i++)
{
if(i!=tep)
{
ret[i].dis=Len(start,ret[i]);
ret[i].cos=COS(start,ret[i]);
}
}
qsort(ret,,sizeof(ret[]),cmp);
for(i=;i<;i++)
printf("%.5lf %.5lf\n",ret[i].x,ret[i].y);
}
return ;
}
整理。
BZOJ 1185: [HNOI2007]最小矩形覆盖-旋转卡壳法求点集最小外接矩形(面积)并输出四个顶点坐标-备忘板子的更多相关文章
- 洛谷 P3187 BZOJ 1185 [HNOI2007]最小矩形覆盖 (旋转卡壳)
题目链接: 洛谷 P3187 [HNOI2007]最小矩形覆盖 BZOJ 1185: [HNOI2007]最小矩形覆盖 Description 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形, ...
- bzoj1185 [HNOI2007]最小矩形覆盖 旋转卡壳求凸包
[HNOI2007]最小矩形覆盖 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 2081 Solved: 920 ...
- 【bzoj1185】[HNOI2007]最小矩形覆盖 (旋转卡壳)
给你一些点,让你用最小的矩形覆盖这些点 首先有一个结论,矩形的一条边一定在凸包上!!! 枚举凸包上的边 用旋转卡壳在凸包上找矩形另外三点... 注意精度问题 #include<cstdio> ...
- BZOJ 1185: [HNOI2007]最小矩形覆盖 [旋转卡壳]
1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 1435 Solve ...
- bzoj 1185 [HNOI2007]最小矩形覆盖——旋转卡壳
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1185 矩形一定贴着凸包的一条边.不过只是感觉这样. 枚举一条边,对面的点就是正常的旋转卡壳. ...
- bzoj 1185 最小矩形覆盖 —— 旋转卡壳
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1185 枚举一条边,维护上.左.右方的点: 上方点到这条边距离最远,所以用叉积求面积维护: 左 ...
- LA 4728 Square ,旋转卡壳法求多边形的直径
给出一些正方形.让你求这些正方形顶点之间的最大距离的平方. //返回点集直径的平方 int diameter2(vector<Point> & points) { vector&l ...
- BZOJ 1185 [HNOI2007]最小矩形覆盖:凸包 + 旋转卡壳
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1185 题意: 给出二维平面上的n个点,问你将所有点覆盖的最小矩形面积. 题解: 先找出凸 ...
- POJ 2187 - Beauty Contest - [凸包+旋转卡壳法][凸包的直径]
题目链接:http://poj.org/problem?id=2187 Time Limit: 3000MS Memory Limit: 65536K Description Bessie, Farm ...
随机推荐
- WebService使用介绍(二)
Soap soap是什么 SOAP 是一种网络通信协议 SOAP即Simple Object Access Protocol简易对象访问协议 SOAP 用于跨平台应用程序之间的通信 SOAP 被设计用 ...
- Reabble.com-KindleRSS新闻杂志订阅
Reabble.com-KindleRSS新闻杂志订阅 TreeInsertions Tomcat部署war包后,运行时出现如下错误 RectangularCovering Reabble.com-K ...
- 51nod 1831 小C的游戏(博弈论+打表)
比较坑的题目. 题意就是:给出一堆石子,一次操作可以变成它的约数个,也可以拿只拿一个,不能变成一个,最后拿的人输. 经过打表发现 几乎所有质数都是先手必败的,几乎所有合数都是先手必胜的 只有几个例外, ...
- 【题解】JLOI2015战争调度
搜索+状压+DP. 注意到一个性质:考虑一棵以x为根的子树,在x到原树的根的路径上的点如果都已经确定了方案,那么x的左右儿子的决策就彼此独立,互不影响了.所以我们考虑状压一条路径上每一层节点的状态,求 ...
- [洛谷P3521][POI2011]ROT-Tree Rotations
题目大意:给一棵$n(n\leqslant2\times10^5)$个叶子的二叉树,可以交换每个点的左右子树,要求前序遍历叶子的逆序对最少.输出最少的逆序对个数 题解:线段树合并,对于每个节点求出交换 ...
- 如何配置开源中国Maven库以加快依赖包下载速度
有时有某些地方由于网络问题,访问maven主仓库比较慢,甚至有可能无法下载某些jar包,此时可以把开源中国Maven库配置到settings.xml文件中,加快依赖包的下载速度. 具体如何配置? 在m ...
- [poj 2274]后缀数组+最长公共子串
题目链接:http://poj.org/problem?id=2774 后缀数组真的太强大了,原本dp是O(nm)的复杂度,在这里只需要O(n+m). 做法:将两个串中间夹一个未出现过的字符接起来,然 ...
- HDU4185:Oil Skimming(二分图最大匹配)
Oil Skimming Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- 自定义toolbar教程
1.写toolbar的布局文件 ,toolbar.xml <?xml version="1.0" encoding="utf-8"?> <Re ...
- 杭电hdu 2089 数位dp
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer). 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍 ...