原本這個算法在筆者電腦裏無人問津過一段時間了,但今天正好作HDU 1007見到了這個問題,今天就來把代碼分享出來吧!ios
咱們首先將全部點按照座標x排序一下,再作一條直線l看成「分割線」,方便咱們遞歸。
算法
而後,咱們就能夠把這些點按照x軸的座標分爲左半部分和右半部分。那麼最短距離必定在左半部分、右半部分、跨越左右的點對中的一個。
ide
那麼你可能會有疑問了:原本最近點對也必定在這三個區域內,這不仍是至關於什麼都沒幹嘛?
spa
還真不是。咱們能夠假設經過遞歸獲得了左邊最小距離爲d1,右邊最小距離爲d2,令δ = min(d1,d2)code
如圖所示,若是跨越左右的點對多是最短距離,那麼它也必然比δ小。而在以l爲中心、最大距離爲2δ的區域中,最多有O(n)個如圖所示的矩形。另外,能夠證實對於每一個矩形區域,最多嘗試8個點對必定能找到最短距離(算法導論第33.4節有詳細的證實,這裏再也不贅述)。排序
所以,咱們能夠寫出遞歸式:T(n)=2T(n/2)+O(n),能夠用主項定理(master method)解得時間複雜度T(n)=O(nlogn)。加上排序一次的時間O(nlogn),所以整個算法的運行時間T(n)' = T(n)+O(nlogn) = O(nlogn)。遞歸
下面,經過這個算法,咱們就能夠寫出一份代碼來:ci
/** * Find closest distance in N points. * Time cost: O(nlogn) * Author: Zheng Chen / Arclabs001 * Copyright 2015 Xi'an University of Posts & Telecommunications */ /** * Algorithm: * First of all, sort the points in ascending order by x. * Divide the array into 2 parts, and find the smallest distance within two parts. * Let min as the smaller one, and find the smallest split distance. */ #include <iostream> #include <algorithm> #include <cmath> #define INF 0x6FFFFFFF using namespace std; struct Node{ double x, y; friend bool operator < (const Node &a, const Node &b){ if(a.x == b.x) return a.y < b.y; return a.x < b.x; } }; Node* Point = NULL; /** * Calculate the distance between two points. * @return [double, the distance between a and b] */ double _distance(const Node a, const Node b) { return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)); } double smaller(double p, double q) { return (p > q) ? q : p; } /** * [Find the closest distance, divide & conquer] * @param left [search from where] * @param right [to where] * @return [double, the smallest distance in the whole set of points] */ double Closest_distance(int left, int right) { double d = INF; double distance_tmp; if(left == right) return 0; if(right == left+1) return _distance( Point[left], Point[right] ); int mid = (left + right) / 2; d = smaller( Closest_distance(left,mid) , Closest_distance(mid,right) ); for(int i=mid-1; i>=left && Point[mid].x - Point[i].x < d; i--){ for(int j = mid+1; j<=right && Point[j].x - Point[mid].x < d && fabs( Point[i].y - Point[j].y) < d; j++){ distance_tmp = _distance( Point[i], Point[j] ); if(distance_tmp < d) d = distance_tmp; } } return d; } int main() { int n; cin>>n; Point = new Node[n]; for(int i=0; i<n ; i++){ cin>>Point[i].x>>Point[i].y; } sort(Point,Point+n); cout<<Closest_distance(0,n-1)<<endl; return 0; }
固然,直接套用這個代碼提交到HDOJ會致使Exceed Time Limit,你懂的^_^
it