用分治法解決最近對問題

2021-10-04 13:38:14 字數 2604 閱讀 4453

1.問題描述

給出在同乙個平面內所有點的座標,然後找出這些點中最近的兩個點的距離。

2.解析

將所給平面上n個點的集合s分成兩個子集s1和s2,每個子集中約有n/2個點。然後在每個子集中遞迴地求最接近的點對。在這裡,乙個關鍵的問題是如何實現分治法中的合併步驟,即由s1和s2的最接近點對,如何求得原集合s中的最接近點對。如果這兩個點分別在s1和s2中,問題就變得複雜了。

為了使問題變得簡單,首先考慮一維的情形。此時,s中的n個點退化為x軸上的n個實數x1,x2,…,xn。最接近點對即為這n個實數中相差最小的兩個實數。顯然可以先將點排好序,然後線性掃瞄就可以了。但我們為了便於推廣到二維的情形,嘗試用分治法解決這個問題。

在二維的情況下:

我們仿照一維的情況先把所有點按照x(橫座標)從左到右公升序排列.

以x橫座標中間的點作為分界線.將平面的點分成左邊和右邊,以上圖為例,分為左邊5個右邊5個.

然後找到左邊的點中最近點對的距離d1,和右邊最近點對的距離d2。

令d=min.那麼d是當前整個平面的最近點對的距離嗎?

答案不是!!

當前的d1,d2都是兩邊各自的點的最近距離,但是沒有考慮到兩邊的點相互配對的情況,即是點對乙個在左邊區域,乙個在右邊區域。如果我們這個時候把兩邊相互配對的所有情況全部羅列出來那麼時間複雜度就變為第一種方法的o(n2).這個時候我們便可以用上面找到的d來限制配對.即是明顯超過d的兩點不需要配對.如下:

那麼在範圍內的只有三個點,也就是說只有這個三個點相互配對的距離才可能比d小.那麼再按照方法一一樣在這些點中找到最短距離再跟d去比較.小的就是當前整個平面中所考慮的所有點中最近點對的距離。

然而在以上問題處理上,有乙個問題尚未解決就是如何找到兩邊區域中的最近點對的距離d1,d2 。

我們可以發現在處理上面這個問題的時候,和最開始處理所有平面的點最近點距離的問題類似,只是點的數目減半了.

那麼我們可以遞迴以上問題.直到劃分的區域中只有乙個或者兩個點.這樣,該區域的最近點對距離就是無窮大或者該兩點的距離。這也是遞迴終止的條件。

3.設計

double

closest_pair

(int left,

int right)

sort

(mpt, mpt + k, cmpy)

;//線性掃瞄

for(i =

0; i < k; i++)}

return d;

}

4.分析分治過程中同時進行歸併排序的分治法,它是分治求最短距離的時候同時對左子集和右子集進行歸併歸併,最終複雜度為t(n) = 2t(n/2) + o(n) = o(nlogn)

然而,按照《資料結構與演算法》黑皮書280頁的描述,取d=min(d1,d2),那麼在mid_x±d區間中平均有√n個點

那麼我們直接對這個區間中的點進行快速排序,再遍歷排序後的點計算每乙個點和最近6個點的距離並更新min就可以。

那麼快速排序需要的時間為o(√n log√n),而遍歷時間小於√n log√n,則總的合併時間為o(√n log√n)

所以,t(n)=2(n/2) + o(√n log√n)

5.原始碼

#include

#include

#include

#include

#include

using

namespace std;

const

double inf =

1e20

;const

int maxn =

100005

;struct pointpoint[maxn]

;int n, mpt[maxn]

;//以x為基準排序

bool

cmpxy

(const point& a,

const point& b)

bool

cmpy

(const

int& a,

const

int& b)

double

min(

double a,

double b)

double

dis(

int i,

int j)

double

closest_pair

(int left,

int right)

sort

(mpt, mpt + k, cmpy)

;//線性掃瞄

for(i =

0; i < k; i++)}

return d;

}int

main()

return0;

}

C 用蠻力法與分治法解決最近對問題

設 p1 x1,y1 p2 x2,y2 pn xn,yn 是平面上n個點構成的集合s,最近對問題就是找出集合s中距離最近的點對。嚴格地講,最接近點對可能多於一對,簡單起見,只找出其中的一對即可。簡單起見,只考慮二維的情況並假設所討論的點以標準笛卡爾座標形式給出。因此,兩個點pi xi,yi 和pj ...

最近對問題(分治法)

include stdafx.h include include using namespace std struct point double distance point a,point b 宣告函式,否則在c 中會出現 找不到標示符 的錯誤 double closestdistance poi...

最近對問題分治法

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