最近對問題

2021-08-10 17:04:28 字數 1938 閱讀 8294

有n個點,求距離最小的一對點。

採用計算出所有點兩兩之間的距離,比較保留最小點距離就可以獲得。這樣時間複雜度為o(

n2)

採用分治的思想來解決問題,可以發現這個問題的難點不在分,而在合併。以下對演算法步驟進行描述:

1. 找到一條線,將問題分解成兩個子集s1

,s2 。(每個子集的大小為n/

2 )

2. 遞迴的發現s1

,s2 中的最小距離點對d1,d2。

3. d=m

in,然後對兩個子集進行合併,因為s1

,s2 的邊緣上可能存在某對點的距離小於d。所以這裡在合併的時候,需要進行處理。

4. 找到s1中距離邊界面距離小於d的所有點,設為集合p。

5. 對於p中的每乙個點,我們都在與其對應的dx

2d的矩陣中,判斷是否有最小值。分析還可以發現這個矩陣中最多有6個值。(如果出現了更多那麼最小值不可能是d)。

6. 依照上述方法進行合併。

closestpair(s):

n= |s|

if(n<2) return;

1. 找到n個點某乙個座標的中位數如x=c,將其劃分為s1,s2

2. d1 = closestpair(s1),d2 = closestpair(s2);

3. d = min(d1,d2);

4. 假設p1是s1中與x=c的距離小於d的集合,假設p2是s2中與x=c的距離小於d的集合。

5. 對於p1中的每乙個點p,找出p2中與之距離最小的點d'。(這裡可以普判斷以減少計算量)

6. d = min

#include

#include

#include

#include"quicksort.h"

using

namespace

std;

struct point

;struct pair

;inline

float computedist(point p1, point p2)

pair closepair(vector

s) if (s.size() == 2)

//將x座標收集到x

int* x = new

int[s.size()];

for (int i = 0; i < s.size(); i++)

quicksort(0, s.size(), x);

int midden = x[s.size() / 2];

//對s進行分組

vector

s1;vector

s2;for (int i = 0; i < s.size(); i++)

//找出子集的最小對

pair d1 = closepair(s1);

pair d2 = closepair(s2);

pair d;

if (d1.dist < d2.dist) d = d1;

else d = d2;

//將s1和s2中與中間距離小於d的點集合至p1,p2中

vector

p1;vector

p2;for (int i = 0; i < s1.size(); i++)

for (int i = 0; i < s2.size(); i++)

// 進行合併找出最小值

for (int j = 0; j < p1.size(); j++)}}

}return d;

}void main()

從**上可以看出主要的易錯點在於邊界條件的判定;(對於此類問題還需要進一步討論),這時再對複雜度進行分析就可以得到t(

n)=2

t(n/

2)+c

n ,所以t(

n)=n

logn

最近對問題

設p1 x1,y1 p2 x2,y2 pn xn,yn 是平面n上n個點構成的集合s,最近對問你就是找出集合s中距離最近的點對。暴力法 在蠻力法實現最近點對問題中,將問題簡化 距離最近的點對可能多於一對,找出一對即可,另外只考慮二維平面中的情況。用距離公式即可求 分治法 分治法思想解決此問題時,首先...

最近對問題

n個點在公共空間中,求出所有點對的歐幾里得距離最小的點對。分解對所有的點按照x座標 或者y 從小到大排序 排序方法時間複雜度o nlogn 根據下標進行分割,使得點集分為兩個集合。解決遞迴的尋找兩個集合中的最近點對。取兩個集合最近點對中的最小值min dis left dis right 合併最近距...

最近對問題

1.解析 1 蠻力演算法 兩層遍歷,將每個點與其他點進行計算,求得最短的距離,複雜度較高,效率低。2 分治演算法 把點集p 點個數為n 按照x軸公升序排序。當n 3時,使用蠻力演算法 當n 3時,將點集分為左右大小為 n 2 和 n 2 的子集pl和pr,通過遞迴呼叫每次將子集一分為二,求得子集中的...