題目:
給定平面上n個點,找其中的一對點,使得在n個點組成的所有點對中,該點對間的距離最小。
演算法核心思想:
嚴格的講,最接近點對可能多於1對,為簡單起見,只找其中的1對作為問題的解。簡單的說,只要將每一點與其它n-1個點的距離算出,找出達到最小距離的2點即可。但這樣效率太低,故想到分治法來解決這個問題。也就是說,將所給的平面上n個點的集合s分成2個子集s1和s2,每個子集中約有n/2個點。然後在每個子集中遞迴的求其最接近的點對。這裡,關鍵問題是如何實現分治法中的合併步驟,即由s1和s2的最接近點對,如何求得原集合s中的最接近點對。如果組成s的最接近點對的2個點都在s1中或都在s2中,則問題很容易解決,但如果這2個點分別在s1和s2中,問題就不那麼簡單了。
s中的點為平面上的點,它們都有兩個座標值x和y。為了將平面上點集s線形分割為大小大致相等的兩個子集s1和s2,選取一垂直線l:x=m來作為分割直線。其中m為s中各點x座標的中位數。由此將s分割為s1=和s2=。從而使s1和s2分別位於直線l的左側和右側,且s=s1∪s2。由於m是s中各點x座標值的中位數,因此s1和s2中的點數大致相等。
遞迴的在s1和s2上屆最接近點對問題,分別得到s1和s2中的最小距離d1和d2。現設d=min。若s的最接近點對(p,q)之間的距離小於d,則p和q必分屬於s1和s2。不妨設p∈s1,q∈s2。p和q距離直線l的距離均小於d。因此,若用p1和p2分別表示直線l的左邊和右邊的寬為d的兩個垂直長條。則p∈p1,q∈p2,如下圖所示。
在二維條件下,p1中所有點與p2中所有點構成的點對均為最接近點對的候選者。由d的意義可知,p2中任何兩個s中的點的距離都不小於d。由此可推出矩陣r中最多只有6個s中的點。由此稀疏性質,對於p1中任一點p,p2中最多只有6個點與它構成最接近點對的候選者。因此,在分治法的合併步驟中,最多隻需要檢查6*n/2=3*n個候選者。但並不確切知道要檢查哪6個點。為解決這問題,可以將p和p2中所有s2的點投影到垂直線l上。由於能與p點一起構成最接近點對候選者的s2中的點一定在d*2d的矩形中,所以它們在直線l上的投影點距p在l上投影點的距離小於d。由上述分析可知,這種投影點最多有6個。因此,若將p1和p2中所有s中點按其y座標排好序,則對p1中所有點,對排好序的點列作一次掃瞄,就可以找出所有最接近點對的候選者。對p1中每一點最多只要檢查p2中排好序的相繼6個點。
演算法步驟如下:
step1:將點對按x座標排序;
step2:如果|s|=1,d=-1;
step3:如果|s|=2,d=這兩個點的距離;
step4:如果|s|=3,d=min;
step5:mid=s中各點x座標的中位數;
step6:ans=min;
step7:q用來記錄所有在s[mid]左右各ans範圍內的座標點,並且按y軸排序,由前面的分析可知這樣的點最多有7個;
step8:求出q中距離最短的兩個點d1,ans=min;
**如下: //
//#include "stdafx.h"
#include #include #include #include #include #include #includeusing namespace std;
#define n 5000
struct point
p[n];
point q[n];//儲存篩選的座標點
point close[2];//儲存最近點對
bool cmpx(const point &c , const point &b)
bool cmpy(const point &c , const point &b)
double square(double x)
double dis(point &a , point &b)//求兩個點之間的距離
double min(double a , double b)
double getthreepoint(int low,int high)
int mid = (low + high)>>1;
ans = min(ans,min( closest(low , mid) , closest(mid + 1 , high) )); //分治法進行遞迴求解
if(ans == -1) return ans;
int i , j , cnt = 0;
for(i = low ; i <= high ; ++i) //把x座標在p[mid].x-ans~p[mid].x+ans範圍內的點取出來 }
sort(q,q+cnt,cmpy);//按y座標進行公升序排序
for(i = 0 ; i < cnt-1 ; ++i)//求在mid點左右各ans距離的點中的最近點對
{ for (j = i + 1; j < cnt && q[j].y - q[i].y < ans; ++j) {
d3 = dis(q[i], q[j]);
//cout<
平面最近點對
求點集中的最近點對有以下兩種方法 設p1 x1,y1 p2 x2,y2 pn xn,yn 是平面上n個點構成的集合s,設計演算法找出集合s中距離最近的點對。1 蠻力法 適用於點的數目比較小的情況下 1 演算法描述 已知集合s中有n個點,一共可以組成n n 1 2對點對,蠻力法就是對這n n 1 2 ...
平面最近點對
求點集中的最近點對有以下兩種方法 設p1 x1,y1 p2 x2,y2 pn xn,yn 是平面上n個點構成的集合s,設計演算法找出集合s中距離最近的點對。1 蠻力法 適用於點的數目比較小的情況下 1 演算法描述 已知集合s中有n個點,一共可以組成n n 1 2對點對,蠻力法就是對這n n 1 2對...
平面最近點對
求點集中的最近點對有以下兩種方法 設p1 x1,y1 p2 x2,y2 pn xn,yn 是平面上n個點構成的集合s,設計演算法找出集合s中距離最近的點對。1 蠻力法 適用於點的數目比較小的情況下 1 演算法描述 已知集合s中有n個點,一共可以組成n n 1 2對點對,蠻力法就是對這n n 1 2對...