最近點對分治演算法

2021-10-10 10:49:23 字數 3619 閱讀 9234

對於平面上給定的 n

nn 個點,給出所有點的座標,即輸入是平面上的 n

nn 個點,輸出是 n

nn 點中具有最短距離的兩點。

法一:暴力,時間複雜度 o(n

2)o(n^2)

o(n2)。

法二:分支,時間複雜度 o(n

log(

n))o(nlog(n))

o(nlog

(n))

。當然,此部落格**二。

對於乙個點我們可以將他們按 y

yy 座標的公升序排序(當然可以反過來),取中間那個點的 y

yy 座標設為 mid

ymidy

midy

作為中間軸,分半,如圖。

對於直線的左右兩邊,都可以用分治,分別求出最小值,令 ans

=min

(兩邊的

最小值)

ans=min(兩邊的最小值)

ans=mi

n(兩邊

的最小值

)。現在就只剩下左右兩邊各取乙個點的情況。我們可以發現,若這個點的 y

yy 座標

dy−a

ns或者

>mi

dy+a

ns\lt midy - ans\ 或者 \gt midy + ans

dy−a

ns或者

>mi

dy+a

ns時,到對稱軸的距離一定 >an

s\gt ans

>an

s,那麼到另一邊的點距離也一定 >an

s\gt ans

>an

s。所以我們就可以將 y

yy 座標離中間直線距離超過 ans

ansan

s 的點全部去掉。

然後我們還發現乙個情況,就是當把乙個點平移到中心軸的時候,只有另一邊的點在以他為圓心,以 ans

ansan

s 為半徑的範圍內才可能有比 ans

ansan

s 小的距離的點,由於圓形難以判斷,我們可以取如下圖這樣乙個矩形。

考慮每乙個格仔,對角線都

s\lt ans

s,如果乙個小格仔裡面有兩個點,在分治的時候 ans

ansan

s 一定會在之前更新,於是不滿足我們之前的假設,所以乙個格仔中最短有乙個點,那麼乙個點最多和 6

66 個點匹配,所以時間複雜度極低,約等於 o(n

log(

n))o(nlog(n))

o(nlog

(n))

。當然,我們反正每次都要進行二分,不如搞個歸併,按照 x

xx 座標排序。對於每兩個點,若 x1−

x2x1-x2

x1−x

2 已經大於 ans

ansan

s 了,便可以直接 bre

akbreak

brea

k,時間複雜度大大降低。

題目描述

在與聯盟的戰鬥中屢戰屢敗後,帝國撤退到了最後乙個據點。

依靠其強大的防禦系統,帝國擊退了聯盟的六波猛烈進攻。

經過幾天的苦思冥想,聯盟將軍亞瑟終於注意到帝國防禦系統唯一的弱點就是能源**。

該系統由 n

nn 個核電站**能源,其中任何乙個被摧毀都會使防禦系統失效。

將軍派出了 n

nn 個**進入據點之中,打算對能源站展開一次突襲。

不幸的是,由於受到了帝國空軍的襲擊,他們未能降落在預期位置。

作為一名經驗豐富的將軍,亞瑟很快意識到他需要重新安排突襲計畫。

他現在最想知道的事情就是哪個**距離其中任意乙個發電站的距離最短。

你能幫他算出來這最短的距離是多少嗎?

其實就是最近點對的板子。先將他們看成一類點,那麼就一共有 2n2n

2n個點,只是計算距離的時候,若他們同為**或核電站,就把距離設為無窮大就行了。

#include
#include

#include

#include

#include

#define ll long long

using

namespace std;

const

int maxn =

4e5+5;

const

double dof =

1e18

;struct node

}arr[maxn]

, c[maxn]

;int t, n, id[maxn]

;double

min(

double x,

double y)

double

dist

(node x, node y)

double

merge_sort

(int l,

int r)

int mid =

(l + r)

>>

1, u = l, v = mid +

1, t = l;

int midy = arr[mid]

.y;// 這條語句要在上一條前

double ans =

min(

merge_sort

(l, mid)

,merge_sort

(mid +

1, r));

while

(u <= mid && v <= r)

int p =0;

while

(u <= mid) c[t ++

]= arr[u ++];

while

(v <= r) c[t ++

]= arr[v ++];

for(

int i = l; i <= r; i ++

) arr[i]

= c[i]

;for

(int i = l; i <= r; i ++)if

(c[i]

.y >= midy - ans && c[i]

.y <= midy + ans) id[

++ p]

= i;

for(

int i =

1; i <= p; i ++

)return ans;

}void

read

(int

&x)int

main()

for(

int i = n +

1; i <=

2* n; i ++)

n <<=1;

sort

(arr +

1, arr +

1+ n)

;printf

("%.3lf\n"

,merge_sort(1

, n));

}return0;

}

最近點對分治演算法 模板

最近點對分治演算法 對於平面上給定的n個點,給出所有點的座標,即輸入是平面上的n個點,輸出是n點中具有最短距離的兩點。分析 maxdis sqrt 2 3 r 2 1 2 r 2 例題可見 具體函式 如下 內含注釋 double dis node a,node b double solve int ...

求最近點對(分治演算法的運用)

原題 條件 多組測試資料,n個點 2 n 100000 接下來輸入n行點對,求點對之間距離的最小值的一半,保留兩位小數。解題思路 以x座標和y座標分別進行歸併排序,當x值相等時,以y值小的在前,當y值相等也是相似。解題 include include include define max 21474...

模板 平面最近點對 分治

傳送門 洛谷 平面最近點對 給定平面上n個點,找出其中的一對點的距離,使得在這n個點的所有點對中,該距離為所有點對中最小的。2 n 200000 一 分治 按x排序,左右分治,邊界處理一下就好了。include include include include include define db do...