【SSL】1726&【洛谷】P1257&【洛谷】P1429平面最近对点
【SSL】1726
Time Limit:10000MS Memory Limit:65536K
Case Time Limit:1000MS
Description
在应用中,常用诸如点、圆等简单的几何对象代表现实世界中的实体。在涉及这些几何对象的问题中,常需要了解其邻域中其它几何对象的信息。例如,在空中交通控制问题中,若将飞机作为空间中移动的一个点来看待,则具有最大碰撞危险的2架飞机,就是这 个空间中最近的一对点。这类问题是计算几何中研究的基本问题之一。下面我们着重考虑平面上的最接近点对的问题。
最接近对点问题的提法是:给定平面上n个点,找出其中的一对点,使得在n个点的所有点对中,该点对的距离最小。严格地说,最接近点对可能多于一对。为了简单起见,这里只限于找其中的一对。
Input
平面中各点的坐标,以0 0结束。
Output
距离最近的两点坐标。
Sample Input
7 2
2 7
3 4
9 7
0 0
Sample Output
3.16
【洛谷】P1257
题目描述
给定平面上 n 个点,找出其中的一对点的距离,使得在这 n 个点的所有点对中,该距离为所有点对中最小的。
输入格式
第一行一个整数 n,表示点的个数。
接下来 n 行,每行两个实数x,y ,表示一个点的行坐标和列坐标。
输出格式
仅一行,一个实数,表示最短距离,四舍五入保留 44 位小数。
输入输出样例
输入
3
1 1
1 2
2 2
输出
1.0000
说明/提示
数据规模与约定
对于100% 的数据,保证
1
≤
n
≤
1
0
4
,
0
≤
x
,
y
≤
1
0
9
1 \leq n \leq 10^4 ,0 \leq x, y \leq 10^9
1≤n≤104,0≤x,y≤109 ,小数点后的数字个数不超过 6。
【洛谷】P1429
题目描述
给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的
输入格式
第一行:n;2≤n≤200000
接下来n行:每行两个实数:x y,表示一个点的行坐标和列坐标,中间用一个空格隔开。
输出格式
仅一行,一个实数,表示最短距离,精确到小数点后面4位。
输入输出样例
输入
3
1 1
1 2
2 2
输出
1.0000
说明/提示
0<=x,y<=109
思路
考虑用分治
ans表示n个点的最近点对距离,先判重,如有点重合ans=0。
否则把n个点尽可能均分为左右两部分,ans的值只有以下3种情况:
①左边部分的最近点对距离d1
②右边部分的最近点对距离d2
③左半部分的点与右半部分点形成的最小距离d3
ans=min(min(d1,d2),d3)
左右两部分的最近点对问题是与原问题结构性质一样的子问题,可以递归求解出d1,d2
d3表示左半部分的点到右半部分点的最短距离,如果存在点对使得d3<d,则点对中的两个点必定都在距离直线L(分界线)d的单位之内。如图所示,它们必定处于以直线L为中心、宽度为2d的垂直带形的区域内。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
struct jgt
{
double x,y;
}a[200010],b[200010];
bool cmp(jgt t1,jgt t2)
{
if(t1.x==t2.x)return t1.y<t2.y;
return t1.x<t2.x;
}
double dis(jgt t1,jgt t2)
{
return sqrt((t1.x-t2.x)*(t1.x-t2.x)+(t1.y-t2.y)*(t1.y-t2.y));
}
double find(int l,int r)
{
if (l==r)return 0x7f7f7f7f;
if (l+1==r)return dis(a[l],a[r]);
int tot=0,mid=(l+r)>>1,i,j;
double d=min(find(l,mid),find(mid+1,r));
for(i=l;i<=r;i++)
if(fabs(a[i].x-a[mid].x)<=d)b[tot++]=a[i];
for(i=0;i<tot;i++)
for(j=i+1;j<tot;j++)
d=min(d,dis(b[i],b[j]));
return d;
}
int main()
{
int n,i;
for(scanf("%d",&n),i=1;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y);
sort(a+1,a+n+1,cmp);
for(i=1;i<n;i++)
if(a[i].x==a[i+1].x&&a[i].y==a[i+1].y){printf("0.0000");return 0;}
printf("%.4f",find(1,n));
return 0;
}