分治 最近點對問題

2022-09-12 18:09:07 字數 2730 閱讀 2908

最近點對問題:

在平面內有點集 s ,s 包含 n 個點。已知每個點的座標 (x, y) ,求最近的兩點之間的距離( n > 2)。如果存在重合的兩個點,最近距離記為0。

列舉的方法時間複雜度是o(n^2),通過分治可以將時間複雜度降為o(nlog(n))

​ 利用一條直線將平面上的所有點集 s 分成兩部分s1、s2,分別計算這兩部分的最短距離d1、d2,再進行合併。合併時,平面上所有點的最短距離為 dis,則 dis 就是d1d2和分別在位於s1 和 s2 的兩個點對的距離d12中最小的那個,即:dis = closest() = min (d1, d2, d12);

首先需要對將 s 中所有點存放在結構體陣列 points[ ] 中(共有 n 個),按照 x 座標的大小將 points[ ] 從小到大進行排序。其中結構體包含點的 x 座標和 y 座標。

求最近點距dis = closest(1, n),有劃分、遞迴、合併三個基本步驟。

劃分:取排序的中間位置處的一條直線mid = l + r,將平面分成左右兩部分s1,s2 如圖。

遞迴:遞迴呼叫求最近點距函式 closest( ) ,分別計算 s1 和 s2 兩個點集的最短距 d1 和 d2。取 d1 和 d2 中較小的那個作為 d 。

合併:計算分別位於 s1 和 s2 的兩個點之間最小的距離 d12。對於 x < mid - d 或者 x > mid + d 範圍內的點,顯然不會出現點距小於 d 的情況。因此只需要在 mid 左右為 d 的範圍內尋找最近的點距。有以下步驟:

將處於mid - d <= x <= mid + d範圍內的點選出來,儲存到selected[ ]陣列中,selected[ ]陣列是乙個臨時陣列,用來存放選出來的點的索引。

將 selected[ ] 按照 y 座標的值從小到大排序。目的是將 y 方向距離比較近的點放在一起。遍歷selected 陣列中的點時,對於每個點最多遍歷出現在它下面相鄰的 6 個點,因此合併是線性複雜度。

最終的最小點距 dis = min(d1, d2, d12)

」最多遍歷6個其他點「 解釋:

​ 對於 selected[ ] 陣列中的每個點,只需要遍歷其下方的點,因為它上方點遍歷其他點的時候已經把它們之間的距離計算過了,所以只需要考慮下方距離為 d ,左右距離也分別為 d 的矩形區域,如下圖。不妨把 mid 線上的點認為屬於s1,那麼由於左側正方形區域中最近距離為 d1 ( < d ), 所以左邊正方形最多存在1、2、5、6 四個點,如果有第5個點,那就一定會有該點與某個點的距離小於 d1 與左側最小距離為 d1 矛盾。除 mid 線上的兩個點外(已經算在左側區域中),右側最多包含3、4、7三個點,其中 7 是分別以3、4為圓心 d2 為半徑的圓弧的交點。所以這個矩形區域內,對於某個遍歷到的點,最多計算它與其他6個點之間的距離

遞迴深度是 log(n) ,每次遞迴的時間複雜度是 nlog(n)(有排序),所以複雜度是 $$o(nlog(n)log(n))$$

#include #include #include #define max 100002

#define inf 1e30

using namespace std;

struct point

points[max];

int selected[max];

bool cmp1(const point &a, const point &b)

bool cmp2(const int &a, const int &b)

// 計算兩個點之間的距離

double len(const int &a, const int &b)

// 計算最近點距

double closest(int l, int r)

}// 把選出來的點,按照y排序

sort(selected, selected + j, cmp2);

// 對於y方向的相距小於min的點,測量距離,更新min

for (int i = 0; i < j; i++)

}return min;

}int main(int argc, char const *ar**)

sort(points, points + n, cmp1);

printf("%.2lf\n", closest(0, n - 1));

}return 0;

}

分治 最近點對問題

利用分治方法的經典問題 最近點對問題 closest pair of points problem 問題描述 n個點在公共空間中,求出所有點對的歐幾里得距離最小的點對。問題分析 該題直觀的解決方法便是brute force 暴力求解 利用分治思想進行求解。首先分析題目,符合分治法的適用條件,規模越小...

最近點對問題 遞迴,分治

問題描述 在二維平面上的n個點中,找出最近的一對點,就是最近點對問題。如下 include include include using namespace std 頂點座標 typedef struct point 操作頂點座標 typedef struct tpoint double d 10e6...

平面最近點對問題 分治

在與聯盟的戰鬥中屢戰屢敗後,帝國撤退到了最後乙個據點。依靠其強大的防禦系統,帝國擊退了聯盟的六波猛烈進攻。經過幾天的苦思冥想,聯盟將軍亞瑟終於注意到帝國防禦系統唯一的弱點就是能源 該系統由n個核電站 能源,其中任何乙個被摧毀都會使防禦系統失效。將軍派出了n個 進入據點之中,打算對能源站展開一次突襲。...