最近点对问题:
源码:
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>
//#define DEBUG
using namespace std;
//point结构体定义
struct point {
double x;
double y;
point(double x, double y) :x(x), y(y) {}
point() { return; }
};
//几个cmp函数, 用于sort
bool cmp_x(const point & A, const point & B){ // 比较x坐标
return A.x < B.x;
}
bool cmp_y(const point & A, const point & B){ // 比较y坐标, 升序
return A.y < B.y;
}
//求两点距离
double distance(const point & A, const point & B){
return sqrt(pow(A.x - B.x, 2) + pow(A.y - B.y, 2));
}
//合并两块划分的区域
double mergePoint(vector<point> & pointVector, double dis, int mid){
vector<point> left, right;
int size=pointVector.size ();
for(int i=0;i<=mid;++i){
if(abs(pointVector.at (i).x-pointVector.at (mid).x)<dis){
left.push_back (pointVector.at (i));
}
}
for(int i=mid+1;i<size;++i){
if(abs(pointVector.at (i).x-pointVector.at (mid).x)<dis){
right.push_back (pointVector.at (i));
}
}
sort(right.begin (),right.end (),cmp_y);
int leftSize=left.size (), rightSize=right.size (), rightNow=0;
for(int i=0;i<leftSize;++i){
rightNow=0;
while(rightNow<rightSize && right.at(rightNow).y<left.at (i).y-dis){
rightNow++;
}
for(int j=0;j<6 && rightNow+j<right.size ();++j){
dis=min(distance (left.at (i),right[j+rightNow]),dis);
}
}
return dis;
}
//求最近点对
double closestPoint(vector<point> & pointVector){
int size=pointVector.size ();
if(size==2){
return distance (pointVector.at (0),pointVector.at(1));
}else if(size==3){
return min(distance (pointVector.at (0),pointVector.at (1)),
min(distance (pointVector.at (0), pointVector.at (2)),
distance (pointVector.at (1),pointVector.at (2))));
}
int mid=size/2-1;
vector<point> left(pointVector.begin (),pointVector.begin ()+mid+1);
vector<point> right(pointVector.begin ()+mid+1, pointVector.end ());
double disL, disR;
disL=closestPoint (left);
disR=closestPoint (right);
double minDis=min(disL, disR);
return mergePoint(pointVector,minDis,mid);
}
//依照OJ的输入格式
int main(){
int rowTime=0;
cin>>rowTime;
while(rowTime-->0){
int numOfPoint=0;
cin>>numOfPoint;
vector<point> points;
double x=0,y=0;
for(int i=0;i<numOfPoint;++i){
cin>>x>>y;
points.push_back (point(x,y));
}
#ifdef DEBUG
for(int i=0;i<numOfPoint;++i){
double x=points.at (i).x, y=points.at (i).y;
printf("(%6f,%6f)\n",x,y);
}
#endif
sort(points.begin (),points.end (),cmp_x );
printf("%.2f\n",closestPoint (points));
}
return 0;
}
源码分析:
测试数据:
4
2
0 0
1 13
0 0
1 1
0 110
9.32 6.09
0.29 5.61
1.94 0.48
0.67 9.00
3.90 3.29
5.97 9.55
1.30 0.33
8.28 2.50
8.73 9.78
6.77 4.45100
2.39 3.48
6.27 8.19
9.16 5.49
4.43 8.26
5.63 5.25
3.49 4.71
9.55 4.07
0.88 0.28
8.86 8.47
7.32 9.37
9.96 2.32
7.60 2.44
8.76 1.35
8.24 7.87
2.87 2.76
9.27 1.83
8.80 9.42
0.10 7.10
1.42 4.86
6.05 7.58
4.38 2.92
0.66 6.68
9.07 3.01
0.90 3.90
6.66 0.36
6.70 6.09
2.50 8.43
3.84 6.76
4.67 9.45
9.10 9.28
8.60 7.66
9.83 7.62
8.18 9.31
5.73 1.31
9.27 2.52
9.24 9.63
5.81 0.21
2.49 3.77
9.73 9.27
2.70 4.65
5.75 9.53
5.41 8.48
9.02 6.82
4.25 1.63
8.75 5.42
9.08 1.42
3.62 6.66
9.52 9.63
5.68 1.78
9.30 1.16
7.56 9.52
7.98 1.00
4.29 0.88
0.34 8.94
5.13 6.20
0.84 3.04
2.45 2.56
9.54 9.49
4.66 2.82
8.80 8.69
7.63 1.04
4.79 4.89
4.19 2.80
6.14 9.42
4.76 3.35
2.57 5.49
2.73 0.70
0.29 6.09
7.30 5.60
6.94 5.14
2.89 5.62
8.54 5.84
8.62 5.78
2.47 9.94
3.54 3.83
5.91 5.66
3.55 4.56
6.22 2.48
3.26 3.57
0.81 5.89
2.25 7.77
6.83 5.98
8.25 6.79
7.58 9.32
1.11 6.77
0.99 5.30
0.63 5.46
7.62 3.87
7.98 5.74
0.09 4.13
5.46 2.51
2.95 9.80
1.39 6.89
2.55 0.39
7.74 9.91
9.15 4.39
5.99 7.66
9.48 4.10
2.53 8.89
6.47 9.79
输出:
1.41
1.00
0.66
0.08