求點集中的最近點對有以下兩種方法:
設p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n個點構成的集合s,設計演算法找出集合s中距離最近的點對。
1、蠻力法(適用於點的數目比較小的情況下)
1)演算法描述:已知集合s中有n個點,一共可以組成n(n-1)/2對點對,蠻力法就是對這n(n-1)/2對點對逐對進行距離計算,通過迴圈求得點集中的最近點對:
2)**描述:
double mindistance = double.maxvalue; //設定乙個mindistance儲存最近點對的距離,初始值為無窮大
int pointindex1,pointindex2; //設定pointindex1,pointindex2分別儲存最近點對的兩個點編號
for (i=1; i< n; i++) //迴圈計算n(n-1)/2對點對的距離}}
} 3)演算法時間複雜度:演算法一共要執行 n(n-1)/2次迴圈,因此演算法複雜度為o(n2)
2、分治法
1)演算法描述:已知集合s中有n個點,分治法的思想就是將s進行拆分,分為2部分求最近點對。演算法每次選擇一條垂線l,將s拆分左右兩部分為sl和sr,l一般取點集s中所有點的中間點的x座標來劃分,這樣可以保證sl和sr中的點數目各為n/2,
(否則以其他方式劃分s,有可能導致sl和sr中點數目乙個為1,乙個為n-1,不利於演算法效率,要盡量保持樹的平衡性)
依次找出這兩部分中的最小點對距離:δl和δr,記sl和sr中最小點對距離δ = min(δl,δr),如圖1:
以l為中心,δ為半徑劃分乙個長帶,最小點對還有可能存在於sl和sr的交界處,如下圖2左圖中的虛線帶,p點和q點分別位於sl和sr的虛線範圍內,在這個範圍內,p點和q點之間的距離才會小於δ,最小點對計算才有意義。
figure 2
對於sl虛框範圍內的p點,在sr虛框中與p點距離小於δ的頂多只有六個點,就是圖二右圖中的2個正方形的6的頂點。這個可以反推證明,如果右邊這2個正方形內有7個點與p點距離小於δ,例如q點,則q點與下面正方形的四個頂點距離小於δ,則和δ為sl和sr中的最小點對距離相矛盾。因此對於sl虛框中的p點,不需求出p點和右邊虛線框內所有點距離,只需計算sr中與p點y座標距離最近的6個點,就可以求出最近點對,節省了比較次數。
(否則的話,最壞情形下,在sr虛框中有可能會有n/2個點,對於sl虛框中的p點,每次要比較n/2次,浪費了演算法的效率)
**描述:
1)對點集s的點x座標和y座標進行公升序排序,獲得點集sx和sy
2)令δ=∞;//δ為最小點位距離
3)divide_conquer(sx,sy,δ)//分治法
if (sx.count=1) thenδ=∞; //如果sx中只有乙個點,則δ=∞
returnδ;
else if(sx.count=2 and d(sx.[0],sx.[1])
δ=d(sx.[0],)sx.[1]);
returnδ;
else//如果sx中多於2個點,則將sx,sy分治,以中心點畫線,將sx分為左右兩部分sxl和sxr,sy分為syl和syr
j1=1,j2=1,k1=1,k2=1;
mid =sx.count/2; //mid為sx中的中間點點號
l =sx.[mid].x; //l為sx中的中間點x座標
for(i=1,i
δl =divide_conquer(sxl,syl,δ);//獲取sx中的的最小點位距離δl
δr =divide_conquer(sxr,syr,δ);//獲取sy中的的最小點位距離δr
δ= min (δl,δr);
δ=merge(syl,syr,δ);//獲sx中sy交界處的最小點位距離,並綜合δl和δr 求出點集的最小點位距離δ
returnδ;
函式merge(syl,syr,δ)
merge(syl,syr,δ)
for(i=1,i
t=1;
for(i=1,i
for( j= max(1,t-3), j<=min(t+3,s'yr.count),j++) //計算s'yr中的點與s'yl[t]y座標相鄰的六個點的距離
return δ
}3)演算法時間複雜度:
首先對點集s的點x座標和y座標進行公升序排序,需要迴圈2nlogn次,複雜度為o(2nlogn)
接下來在分治過程中,對於每個s'yl中的點,都需要與s'yr中的6個點進行比較
o(n)= 2o(n/2) + (n/2)*6 (乙個點集劃分為左右兩個點集,時間複雜度為左右兩個點集加上中間區域運算之和)
其解為o(n)< o(3nlogn)
因此總的時間複雜度為o(3nlogn),比蠻力法的o(n2)要高效。
hdu1007最近點對
效率不太高,10^6的資料用了2s。。。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <
stdio.h
>
#include <
string.h
>
#include <
math.h
>
#include <
algorithm
>
#define eps 1e-8
#define d(a) ((a)*(a))
using namespace std;
const int n=100005;
struct nodenode[n];
int n,cnt;
bool cmpx(node a,node b)
bool cmpy(node a,node b)
double dis(node a,node b)
double solve(int le,int ri)
return ret;
}
int main()
}
平面最近點對
求點集中的最近點對有以下兩種方法 設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對...