CodeVS2319 最近最远点对
来源:互联网 发布:wps表格怎么刷新数据 编辑:程序博客网 时间:2024/05/18 02:02
http://codevs.cn/problem/2319/
题意:给定笛卡尔平面内的若干个点,求最近两点的距离和最远两点的距离,距离是欧氏距离,点数不大于100,000。
对于最近点对考虑分治的做法:用一条直线将所有点分成两部分,对于两部分的点进行分治,然后考虑两部分联合的结果。
可以先把所有点按纵坐标排序,这样就容易用平行于x轴的直线划分。设两边分别求出的结果的较小值是d,我们只需考虑直线两侧离直线距离d以内的所有点即可。
考虑枚举直线某一侧的所有点,对于每个点,在直线另一侧到该点距离小于d的点,是有常数性的限度的。
假设这个点离直线非常非常近,或者就在直线上,以该点为圆心,d为半径所作出的圆在直线另一侧的部分是一个劣弓形,或者半圆。
直线另一侧的一个点若要到该点的距离小于d,则必须落在这个弓形或半圆以内。一个小小的半圆里面能有多少个点呢?注意到在这些点中,所有点对的距离不小于d!
最多只有5个点。事实上,具体算法实现非常简单。对前一半点和后一半点进行分治,然后两重循环枚举前一半点和后一半中的前五个点,计算距离并更新即可。
对于最远点对,显然答案中的两个点一定在整个点集的凸包上,凸包可以用Graham算法来求出。然后旋转卡壳即可。
关于旋转卡壳,我们这里要找的就是在凸包上,与每个点距离最远的另一个点,设凸包上的若干个点依次是p[]号点,离p[i]号点最远的点是f[i]号点。
则对于顺时针依次的p[i]和p[i+1],其答案f[i]和f[i+1]也一定按顺时针排列,这是比较显然的,于是可以用单调队列来求出f[],选出最远的一对即可。
代码:
#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<map>#include<set>#include<bitset>#include<queue>#include<stack>#include<cmath>#include<climits>#define rpt(i,l,r) for(i=l;i<=r;i++)#define rpd(i,r,l) for(i=r;i>=l;i--);#define maxn 100005using namespace std;struct point{ double x,y;};point a[maxn],b[maxn*2];int n,i;double ans1=INT_MAX,ans2=0;bool cmp1(point A,point B){ return A.y<B.y;}bool clockwise(point A,point B,point C){ return A.x*B.y+B.x*C.y+C.x*A.y-A.y*B.x-B.y*C.x-C.y*A.x<0;}bool cmp2(point A,point B){ return clockwise(A,a[1],B);}double dist(point A,point B){ double distx=A.x-B.x,disty=A.y-B.y; return sqrt(distx*distx+disty*disty);}void input(){ scanf("%d",&n); rpt(i,1,n) scanf("%lf%lf",&a[i].x,&a[i].y);}void solve1(int l,int r){ if(l<r){ int m=l+r>>1,i,j,k; double tmp; solve1(l,m); solve1(m+1,r); rpt(i,l,m) rpt(j,m+1,min(m+5,r)){ tmp=dist(a[i],a[j]); if(tmp<ans1) ans1=tmp; } }}void solve2(){ int k=2,j=1; double tmp; b[1]=a[1],b[2]=a[2]; rpt(i,3,n){ while(k>1&&clockwise(b[k-1],b[k],a[i])) k--; b[++k]=a[i]; } rpt(i,1,k) b[k+i]=b[i]; rpt(i,1,k){ while(dist(b[i],b[j])<dist(b[i],b[j+1])+1e-6) j++; tmp=dist(b[i],b[j]); if(tmp>ans2) ans2=tmp; }}int main(){ input(); sort(a+1,a+n+1,cmp1); solve1(1,n); sort(a+2,a+n+1,cmp2); solve2(); printf("%.2f %.2f\n",ans1,ans2); return 0;}
0 0
- CodeVS2319 最近最远点对
- 最近&最远点对
- SDOI2012最近最远点对
- [SDOI2012] 最近最远点对
- 点集中的最近点 最远点对
- 寻找最远点对
- 寻找最远点对
- 寻找最远点对
- 寻找最远点对
- 寻找最远点对
- 寻找最远点对
- POJ2187-最远点对
- 求最远点对
- 平面最远点对
- 平面最远点对距离
- poj 2187 最远点对
- HDU1007-Quoit Design(求最近点对,求最远点对(凸包+旋转卡壳))
- 旋转卡壳 求最远点对
- windows-linux
- Leetcode Clone Graph
- [LeetCode Problem]TwoSum
- 如何将PreparedStatement查询得到的结果集存储起来--方法一:采用对象数组
- BIOS入门之我见-开篇
- CodeVS2319 最近最远点对
- 安卓控件使用系列35:ListView列表控件显示表单的使用方法2
- win8和win10下,visual studio 2008 调试出现无响应的卡死问题解决
- 把sshkey添加到git agent上
- RPC协议、http协议、tcp/ip协议、udp协议、socket协议以及soap协议都有什么相同点和不同点
- (ZT) CHS conversion
- CCS3.3的使用2___统计程序运行的时间
- 我不经常用的
- 如何将PreparedStatement查询得到的结果集存储起来--方法二:采用列表List