演算法:
0:把所有的點按照橫座標排序
1:用一條豎直的線l將所有的點分成兩等份
2:遞迴算出左半部分的最近兩點距離d1,右半部分的最近兩點距離d2,取d=min(d1,d2)
3:算出「乙個在左半部分,另乙個在右半部分」這樣的點對的最短距離d3。
4:結果=min(d1,d2,d3)
關鍵就是這第3步。貌似這需要n^2的時間,把左邊每個點和右邊每個點都對比一下。其實不然。秘密就在這裡。 首先,兩邊的點,與分割線l的距離超過d的,都可以扔掉了。 其次,即使兩個點p1,p2(不妨令p1在左邊,p2在右邊)與分割線l的距離(水平距離)都小於d,如果它們的縱座標之差大於d,也沒戲。 就是這兩點使得搜尋範圍大大減小: 對於左半部分的,與l的距離在d之內的,每個p1來說:右半部分內,符合以上兩個條件的點p2最多只有6個! 原因就是: d是兩個半平面各自內,任意兩點的最小距離,因此在同乙個半平面內,任何兩點距離都不可能超過d。 我們又要求p1和p2的水平距離不能超過d,垂直距離也不能超過d,在這個d*2d的小方塊內,最多只能放下6個距離不小於d的點。 因此,第3步總的比較距離的次數不超過n*6。
第3步的具體做法是:
3.1 刪除所有到l的距離大於d的點。 o(n)
3.2 把右半平面的點按照縱座標y排序。 o(nlogn)
3.3 對於左半平面內的每個點p1,找出右半平面內縱座標與p1的縱座標的差在d以內的點p2,計算距離取最小值,算出d3。 o(n*6) = o(n) 因為3.2的排序需要o(nlogn), 所以整個演算法的複雜度就是o(n((logn)^2))。
/** 最近點對問題,時間複雜度為o(n*logn*logn)
*/#include
#include
#include
#include
#include
using
namespace
std;
const
double inf =1e20;
const
int n = 100005
;
struct
point
point[n];
intn;
inttmpt[n];
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(tmpt,tmpt+k,cmpy);
//暴力搜尋 tmpt中的最短距離
for(i = 0; i < k; i++)
} return
d;
}
intmain()
return
0;
}
平面最近點對問題 分治
在與聯盟的戰鬥中屢戰屢敗後,帝國撤退到了最後乙個據點。依靠其強大的防禦系統,帝國擊退了聯盟的六波猛烈進攻。經過幾天的苦思冥想,聯盟將軍亞瑟終於注意到帝國防禦系統唯一的弱點就是能源 該系統由n個核電站 能源,其中任何乙個被摧毀都會使防禦系統失效。將軍派出了n個 進入據點之中,打算對能源站展開一次突襲。...
平面最近點對問題 分治
1 演算法描述 已知集合s中有n個點,一共可以組成n n 1 2對點對,蠻力法就是對這n n 1 2對點對逐對進行距離計算,通過迴圈求得點集中的最近點對 2 演算法時間複雜度 演算法一共要執行 n n 1 2次迴圈,因此演算法複雜度為o n2 實現 利用兩個for迴圈可實現所有點的配對,每次配對算出...
分治法求平面最近點對入門
一.平面最近點對問題.平面最近點對 在乙個平面上有n nn個點,求出距離最近的兩個點.平面最近點對是計算幾何中乙個十分經典且基礎的問題,通常採用分治法來解決.二.直線最近點對的分治法.在用分治法解決平面最近點對之前,我們用分治法來解決一下直線最近點對問題.考慮在一條直線上暴力列舉兩個點並計算距離取最...