二维点对,先随机生成平面点,再把平面上的点划分成左右两部分,我觉得其实无所谓左右点的多少,对结果没有影响,记录最短距离的点,比较中线附近的点的距离。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
using namespace std;
const double INF = 1e20;//相当于正无穷
const int N =10000;
struct Point
{
double x, y;//二维点的横纵坐标
}point[N];
int tmpt[N];
void setpoints(Point point[], int num);
float dis(int a, int b);
void paixu1(Point L[], int num);
double min(double a, double b);
double Closest_Pair(int left, int right, Point &p, Point &q);
int main()
{
int num;
cout << "输入点的个数:";
cin >> num;
Point p, q;//距离最近的两个点``
setpoints(point, num);//创造散点
cout << "用分治法求最近对:" << endl;
cout << "对散点的x进行排序:" << endl;
paixu1(point, num);//x排序
cout << endl << endl;
double d;
//DivideConquer( 0,num-1);
d = Closest_Pair(0, num - 1,p,q);
cout << "距离最近的两点为:" << "(" << p.x << "," << p.y << ")" << "与" << "(" << q.x << "," << q.y << ")";
//cout << "距离最近的两点为:" << "(" << point[p].x << "," << point[p].y << ")" << "与" << "(" << point[q].x << "," << point[q].y << ")";
cout << "两点之间的最短距离为:" << sqrt(d) << endl;
system("pause");
return 0;
}
void setpoints(Point point[], int num)
{
for (int i = 0; i < num; i++)
{
point[i].x = (rand() % 201-100) ;
point[i].y = (rand() % 201-100 );
}
for (int i = 0; i < num; i++)
{
cout << "第" << i + 1 << "个点的坐标" << "(" << point[i].x << "," << point[i].y << ")" ;
if ((i + 1) % 5 == 0) cout << endl;
}
}
//求两点的距离的平方
float dis(int a, int b)
{
return (point[a].x - point[b].x)*(point[a].x - point[b].x) + (point[a].y - point[b].y)*(point[a].y - point[b].y);
}
void paixu1(Point L[], int num)
{
float t, m;
for (int i = 0; i < num; i++)
{
for (int j = 0; j < num - i - 1; j++)
{
if (L[j].x >L[j + 1].x)
{
t = L[j].x; m = L[j].y;
L[j].x = L[j + 1].x; L[j].y = L[j + 1].y;
L[j + 1].x = t; L[j + 1].y = m;
}
}
}
cout << endl;
for (int i = 0; i < num; i++)
{
cout << "第" << i + 1 << "个点的坐标" << "(" <<L[i].x << "," << L[i].y << ")";
//min = L[0].x; max = L[num - 1].x;
if ((i + 1) % 5 == 0) cout << endl;
}
}
bool cmpy(const int& a, const int& b)
{
return point[a].y < point[b].y;
}
double min(double a, double b)
{
return a < b ? a : b;
}
double Closest_Pair(int left, int right,Point &p,Point &q)
{
double d = INF;
if (left == right)
{
return d;
}
if (left + 1 == right)
return dis(left, right);
int mid = (left + right) /2;
double d1 = Closest_Pair(left, mid,p,q);//随着调用mid,left right 都在改变
Point d1p = p;
Point d1q = q;//保存左支最近两个点的点数据
double d2 = Closest_Pair(mid + 1, right,p,q);//得到右支的最短距离点数据
d = min(d1, d2);
if (d1 < d2) {
d = d1;
p = d1p;
q = d1q;
}
else { //此时并不需要更新p,q的值,因为此时p和q的值就是右支的最小的一对点的坐标
d= d2;
}
int i, j, k = 0;
//分离出宽度为d的区间
for (i = left; i <= right; i++)
{
if (fabs(point[mid].x - point[i].x) <= d)//fabs求绝对值函数,记录在中点左右两边距离中点坐标小于左右两边最小距离的点的个数
tmpt[k++] = i;
}
sort(tmpt, tmpt + k, cmpy);//排序函数,(首地址,尾地址,排序方式)
for (i = 0; i < k; i++)
{
for (j = i + 1; j < k && point[tmpt[j]].y - point[tmpt[i]].y<d; j++)
{
double d3 = dis(tmpt[i], tmpt[j]);
if (d > d3)
{
d = d3;
p.x = point[tmpt[i]].x; p.y = point[tmpt[i]].y;
q.x = point[tmpt[j]].x; q.y = point[tmpt[j]].y;
}
}
}
return d;
}
希望我的代码对你的学习有帮助