問題描述:
最近點對問題是指求解平面點集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步。貌...