您的位置:首页 > 其它

最近点对问题 Swust Oj 794

2016-04-12 22:52 344 查看
Swust oj 794

问题描述:

设p1=(x1,
y1),
p2=(x2,
y2),
…, pn=(xn,
yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。

多组测试数据,第一行为测试数据组数n(0<n≤100),每组测试数据由两个部分构成,第一部分为一个点的个数m(0<m≤1000),紧接着是m行,每行为一个点的坐标x和y,用空格隔开,(0<x,y≤100000)

每组测试数据输出一行,为该组数据最近点的距离,保留4为小数。

#include<stdio.h>
#include<cmath>
#include<algorithm>

#define MAX 1001
#define INF 1000000001
struct Point
{
double x, y;
}point[MAX];

int n, temp[MAX];
bool cmp(Point a, Point b) // 点按照从左到右从下到上的方式排序
{
if (a.x != b.x)
{
return a.x < b.x;
}
else
{
return a.y < b.y;
}
}

bool cmpy(int a,int b)      /按照y值大小排序
{
return point[a].y < point[b].y;
}
double Min(double a, double b)        //两个数的最小值,用来更新结果。
{
return a < b ? a : b;
}

double Distance(int i, int j)        //计算两个点的距离
{
return sqrt((point[i].x - point[j].x) * (point[i].x - point[j].x) + (point[i].y - point[j].y) * (point[i].y - point[j].y));
}

double Marge(int left, int right)               //这里的参数为点集合的左右
{
double d = INF;
if (left == right)              //如果左边的点等于右边的点,结束,返回d值
return d;
if (left + 1 == right)            //如果是挨着的两个点,计算距离()划分到最小时
{
return Distance(left, right);
}
int mid = (left + right) / 2;              //分治
double dis_left = Marge(left, mid);
double dis_right = Marge(mid+1, right);
d = Min(dis_left, dis_right);          //让d 为分治后的最小距离
int i, j;
int k = 0;
for (i = left; i <= right; i++)             //处理夸区域问题
{
if (fabs(point[i].x - point[mid].x) <= d)             //如果跨区域的点之间的距离小于等于d,那么我们就要加入数组做处理
{
temp[k++] = i;
}
}
sort(temp, temp + k, cmpy); 按照y值的从小到大排序
for (i = 0; i < k; i++)
{
for (j = i + 1; j < k &&point[temp[j]].y - point[temp[i]].y < d; j++) //求出跨区域的最短距离
{
double temp_dis = Distance(temp[i], temp[j]);
if (d>temp_dis)                                    ///得出结果
{
d = temp_dis;
}
}
}
return d;
}
int main()
{
int n, T;
scanf("%d",&n);
int i;
while (n > 0)
{
scanf("%d",&T);
for (i = 0; i < T; i++)
{
cin >> point[i].x >> point[i].y;
}
sort(point, point + T, cmp);
printf( "%.4lf\n",Marge(0, T-1));
n--;
}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: