题目:传送门
解答:直接暴力求解肯定会超时。此题核心就是求出来最近的一对点之间的距离,即最近点对算法。
简要来说就是利用分治的思想,左半边的最小距离,与右半边的最小距离比较,得到一个mindist。再遍历分界线左右 mindist 范围内点的间距,取最小值。
这样,需要暴力的只有分界线周围的点。但是我第一次提交版本还是超时。询问之后是因为优化不够,写在trick中。
这里一些trick:
#include <stdio.h> #include <stdlib.h> #include <iostream> #include <vector> #include <map> #include <algorithm> #include <math.h> #include <string> #include <string.h> #define MAXDIST 1000000 using namespace std; struct Point{ double x; double y; }; int n; double x, y; bool tag; Point tmp; double eps = 1e-8; Point gao[100005]; bool cmpxy (const Point a, const Point b) { if(a.x != b.x) { return a.x < b.x; } else { return a.y < b.y; } } bool cmpx (const Point a, const Point b) { return a.x < b.x; } bool cmpy (const Point a, const Point b) { return a.y < b.y; } double dist(const Point a, const Point b) { return ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } double nearestPair(int head, int tail) { if(head == tail) { return MAXDIST; } if(head + 1 == tail) { return dist(gao[head], gao[tail]); } int mid = (head + tail) >> 1; double d1 = nearestPair(head, mid); double d2 = nearestPair(mid + 1, tail); double mindist = d1 > d2 ? d2 : d1; for(int i = head; i<=tail; i++) { // 不能和自身比较,否则距离为 0 if(i != mid && gao[i].x > (gao[mid].x - mindist) && gao[i].x < (gao[mid].x + mindist)) { if(dist(gao[i], gao[mid]) < mindist) mindist = dist(gao[i], gao[mid]); } } return mindist; } int main() { while(cin>>n && n!= 0) { memset(gao, 0, sizeof(gao)); tag = false; for(int i=0; i<n; i++) { scanf("%lf%lf", &x, &y); tmp.x = x; tmp.y = y; gao[i] = tmp; } sort(gao, gao + n, cmpxy); for(int i=0; i < n-1; i++) { if(fabs(gao[i].x - gao[i+1].x) < eps && fabs(gao[i].y - gao[i+1].y) < eps) tag = true; } if(tag) { cout<<"0.00"<<endl; continue; } else { double d = nearestPair(0, n-1); printf("%.2f\n", sqrt(d)/2); } } return 0; }
原文地址:http://blog.csdn.net/ironyoung/article/details/45420493