對於平面上給定的 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...