最近點對問題

2021-07-23 08:54:28 字數 2337 閱讀 4066

該問題的形式化表示:

input:平面上有n個點

output:歐式距離最近的點對

1 暴力破解法,列舉出這個平面所有的點對,找出最小的那個點對,所需要的時間複雜度為o(n^2)

2 用分而治之的思想

(1) 將平面上的點均分成左右兩部分

分別求出左,右兩邊最近點對的距離d1,d2,δ =min(d1,d2)

然後我們需要考慮的是,是否存在來自分割線左右兩側的點其距離比 δ 還小,所以也需要計算分割線左右兩側的點組成的點對,如果將左右兩側的所有點對列舉出來,時間開銷為o(n^2)

但是,在演算法中由於我們的目標是找到比 δ 還小的點對,所以我們只需要計算l區域內的點,l區域的寬度為 2δ

進一步分析

是否l區域內的所有點我們都需要進行計算,我們將l條帶進行分割,如下圖,格仔的邊長為 δ/2 ,顯然乙個格仔中最多有乙個點,因為如有兩個點落在同乙個格仔中,則這兩點的距離小於 δ 。

同樣的我們在y軸方向進行分析,對於點 i 也只需要在2rows的區域內進行計算。因此對於任意乙個l區域內分割線左邊的點,其實最多隻需要計算右邊6個點即可。

**如下

#include 

#include

#include

#include ;

#include

using

namespace

std;

#define min(a,b) ((a)

struct point v[10000] ;

//儲存l區域內的點

int v_strip[10000];

//計算兩點之間的歐式距離

inline

double dis( point a, point b )

int comx(const point &a,const point &b)

int comy(const

int &a,const

int &b)

//分治法求最近點對

//先將所有的點在x軸方向上排序

double closestpairpre(int n)

double closestpair (int low, int high)

if ( (high-low)==1 )

//divide and conquer

int mid = (low+high)>>1 ;

double dis_left = closestpair(low, mid) ;

double dis_right = closestpair(mid+1, high) ;

double dis_min = min(dis_left,dis_right) ;

//record points in the 2*dis_min strip by x-coordinate

int strip_low=0, strip_num=0 ;

for (int i = low; i <= high; ++i)

}sort(v_strip, v_strip+strip_num, comy);

//在strip中對任何一點,只需要和另一邊的6個比較

for (int i = strip_low; i < strip_num; ++i)

}return dis_min;

}

最近點對問題

在n n 1 個點的集合中尋找最近點對。即求任意兩點的歐幾里得距離的最小值。1 最簡單的暴力搜尋演算法,時間複雜對為o n n 2 這裡主要考慮分治演算法,執行時間的遞迴式為t n 2 t n 2 o n 時間複雜度為o n lgn 演算法思想 將集合中的點按x座標排序,我們可以想象一條垂直的直線將...

最近點對問題

在二維平面上的n個點中,如何快速的找出最近的一對點,就是最近點對問題。一種簡單的想法是暴力列舉每兩個點,記錄最小距離,顯然,時間複雜度為o n 2 在這裡介紹一種時間複雜度為o nlognlogn 的演算法。其實,這裡用到了分治的思想。將所給平面上n個點的集合s分成兩個子集s1和s2,每個子集中約有...

最近點對問題

最近點對問題,是分治法的乙個典型應用,可以作為分治法入門的乙個切入點。最近點對問題的描述比較簡單,在二維平面中,給定一堆點,求距離最近的一對點,思路是,講這一堆點分為兩部分,左域與右域,如何劃分左域右域呢?我們知道,這一堆點,每乙個點都有其橫座標,假如有十個點,對應十個橫座標,我們就取其中間數,然後...