- 算法说明
先将坐标系中的点按横坐标的大小进行排序,从中位数大小位置开始分割,独立的求两边的最短距离,去最小值,之后以这个中位线处往两边扩展最小值个长度,求改范围的最小值,比较三者,得出问题的最小值。对于求两边的最小值问题,递归调用。
- 源代码
#include <iostream>
#include <cmath>
#include <ctime>
#include <vector>
#include <algorithm>
using namespace std;
struct point {
int x, y;
point(int xx, int yy) {
x = xx;
y = yy;
}
};
#define here(a) printf("here %d\n", a);
#define ptf printf("\n");
vector<point> p;
bool cmp(point a, point b);
double minDistance(double a, double b);
double twoPointDistance(point a, point b);
double closestPoint(int n, int m);
int main(int argc, char* argv[]) {
freopen("cloestPointInput.txt", "r", stdin);
int n, x, y;
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%d%d", &x, &y);
p.push_back(point(x, y));
}
for(int i = 0; i < p.size(); i++) {
printf("(%d,%d)\n", p[i].x, p[i].y);
}
sort(p.begin(), p.end(), cmp);
double min = closestPoint(0, n);
freopen("cloestPointOutput.txt", "w", stdout);
printf("TwoPointMinDistance = %.2f", min);
return 0;
}
bool cmp(point a, point b) {
if(a.x != b.x) return a.x < b.x;
return a.y < b.y;
}
double minDistance(double a, double b) {
if(a < b) return a;
return b;
}
double twoPointDistance(point a, point b) {
return sqrt(fabs(a.x - b.x) * fabs(a.x - b.x) + fabs(a.y - b.y) * fabs(a.y - b.y));
}
double closestPoint(int n, int m) {
if(m - n == 2) return twoPointDistance(p[n], p[n + 1]);
if(m - n == 3) {
double b1 = twoPointDistance(p[n], p[n + 1]);
double b2 = twoPointDistance(p[n], p[n + 2]);
double b3 = twoPointDistance(p[n + 1], p[n + 2]);
b2 = min(b1, b2);
b3 = min(b2, b3);
return b3;
}
int mid = (n + m) / 2;
double d1 = closestPoint(n, mid);
double d2 = closestPoint(mid, m);
double dm = minDistance(d1, d2);
int l = n, r = m - 1;
while(p[mid].x - dm > p[l].x && l <= m) l++;
while(p[mid].x + dm < p[r].x && r >= n) r--;
double temp;
for(int i = l; i < r; i++) {
if(p[i + 1].y - p[i].y > dm) continue;
else {
temp = twoPointDistance(p[i], p[i + 1]);
dm = min(temp, dm);
}
}
return dm;
}
- 输入数据
- 运行结果