平面最近點對問題求解

2021-07-15 12:51:32 字數 2090 閱讀 5343

問題描述:

最近點對問題是指求解平面點集n個點中距離最近的兩個點間的問題。為簡單起見,在二維座標平面來考慮該問題。如果說討論的點以標準二維座標給出,則有點

本章主要通過兩種方法來求解

蠻力法分治法

顧名思義,蠻力法指的就是通過遍歷所有解之後通過對比求出最近點對問題。

基本思路:

對平面中的n個點兩兩進行組隊,計算並記錄最小距離。這裡需要注意兩個問題,其一,點對之間的距離是沒有方向性的,即dis( pi , pj )=dis,( pj , pi ),所以任意兩點只需要計算一次即可。其二,計算的時候如果只是求解大小,可以不同開方,這樣有一定的優化,簡化了公式的計算。

#include "stdio.h"

#include "math.h"

double point[100001][2];

int main()

return

0;}

分治法思路:

1) 把它分成兩個或多個更小的問題;

2) 分別解決每個小問題;

3) 把各小問題的解答組合起來,即可得到原問題的解答。小問題通常與原問題相似,可以遞迴地使用分而治之策略來解決。

這裡的分治演算法的主要思路是將平面上的n個點分為兩個子集s1,s2。每個子集中有n/2個點,然後遞迴的在每個子集中求解最近點對,兩邊求得的結果如圖所示:

那麼可以看出左邊的最近點對的距離為d1,右邊為d2.但是最近對可能乙個點在s1中而另乙個點在s2中。這樣,我們,就要去想辦法對其進行合併,然後求得合併區域的最近對距離,假設為d3,那麼只需要比較d1,d2,d3的大小關係即可,最小的就是平面最近對的距離。通過分析我們可以知道,如果存在這樣的最近對的點,那麼這個點在s1集合中,肯定是橫座標最靠近中位線l的點,s2中同理。那麼這個範圍如何劃定呢?

d=min(d1,d2)假定中位線橫座標為x,那麼範圍就是[x-d,x+d].這個範圍是怎麼劃定的呢?根據平面中點的位置我們就可以知道,兩點的距離為橫縱座標之間的差值的平方和。那麼如果要存在這樣的點,他們之間的橫座標之間的差值的絕對值必須要小於等於d(這裡包括這點恰好就在中位線l上)。這樣可以篩選出橫座標為[x-d,x+d]的區域。如下圖所示:

可以看出這個區域中包含三個點,只需要求出這三個點之間的最近點對即可(蠻力法)。這裡還需要注意一點,上面是通過橫座標篩選的這個區域,這裡可以根據縱座標將縱座標差的絕對值大於d的座標剔除。

這裡是分治法求解**:

#include "stdio.h"

#include "math.h"

#include

#include "algorithm"

#define max 100005

const

double inf = 1e20;

struct point;

point p[max];

int ans[max];

double dis(point p1,point p2)

bool cmpy(const

int & a,int& b)

bool compxy(const point& p1,point& p2)

//通過排序,確定這寫點按照縱座標公升序

std::sort(ans, ans + k, cmpy);//線性掃瞄

for(i=0;i1;i++)

int main()

return

0;}

up_junior1.

*. ↩

平面最近點對問題

平面最近點對問題正如其名,給定平面上的 n 個點,找出其中的一對點,使得這對點的距離在所有點對中最小。首先顯而易見地我們可以得到這個問題的 o n 2 演算法,列舉所有點對即可。但是很顯然我們可以注意到,這裡面有很多點對顯然不是最優的,那麼我們可以想到一種剪枝方法,就是將只對x座標差值小於當前已知最...

平面最近點對問題詳解

演算法 0 把所有的點按照橫座標排序 1 用一條豎直的線l將所有的點分成兩等份 2 遞迴算出左半部分的最近兩點距離d1,右半部分的最近兩點距離d2,取d min d1,d2 3 算出 乙個在左半部分,另乙個在右半部分 這樣的點對的最短距離d3。4 結果 min d1,d2,d3 關鍵就是這第3步。貌...

平面最近點對問題詳解

演算法 0 把所有的點按照橫座標排序 1 用一條豎直的線l將所有的點分成兩等份 2 遞迴算出左半部分的最近兩點距離d1,右半部分的最近兩點距離d2,取d min d1,d2 3 算出 乙個在左半部分,另乙個在右半部分 這樣的點對的最短距離d3。4 結果 min d1,d2,d3 關鍵就是這第3步。貌...