平面最近點對 cdq分治

2021-09-29 16:02:05 字數 2283 閱讀 5768

cdq分治可以很好地處理平面點對間具有某種性質的值或數量,最近點對也不例外。

參考oi wiki

先對x排序,cdq返回點集內部最近點對的距離記為mindis。

考慮如何合併左右區間,對於處於點集a的點a和b的點b,顯然

∣ a.

x−b.

x∣

<=m

indi

s|a.x-b.x|<=mindis

∣a.x−b

.x∣<=m

indi

s設a,b屬於c,找到c後,對於點p,k屬於c,顯然也要滿足

∣ p.

y−k.

y∣

<=m

indi

s|p.y-k.y|<=mindis

∣p.y−k

.y∣<=m

indi

s可以證明,對於點p,c中滿足上述性質的點不會超過7個,因為

∣ p.

x−k.

x∣

<=m

indi

s|p.x-k.x|<=mindis

∣p.x−k

.x∣<=m

indi

s,∣p.y

−k.y

∣<=m

indi

s|p.y-k.y|<=mindis

∣p.y−k

.y∣<=m

indi

s,把區間分為2個正方形,正方形邊長為mindis,對於每個正方形,再分為4個小正方形,而且每個小正方形內部最多有1個點,因為如果有大於兩個點,那麼,存在點x,y,,使得

d is

(x,y

)

rt(2

(min

dis2

)2

)

ndis

dis(x,y)di

s(x,

y)rt(2

(2mi

ndis

​)2)

ndis

也就是說,我們每次合併兩個點集,計算點x時,與點y的dist中,y與x屬於同乙個集合的個數最多為7個,即計算時無效的計算最多為7次。

所以,為了方便計算,我們將cdq後的點按y的大小歸併。

raid

給定兩個點集,計算點集之間的最小距離。

給每個點加個flag,flag相同的點為同乙個點集,距離為inf

#include

using

namespace std;

char buf[

1<<20]

,*p1=buf,

*p2=buf;

#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?eof:*p1++)

#define tt templateinline

tt bool

read

(t &x)

while(47

58)x=

(x<<3)

+(x<<1)

+(c^48)

,c=gc()

;if(f)x=

-x;return1;

}tt void

print

(t x)

tt bool

read

(t&a,t&b)

tt bool

read

(t&a,t&b,t&c)

typedef

long

long ll;

const ll maxn=

1e5+8;

#define lowbit(x) (x&(-x))

struct pointpoint[maxn<<1]

,tmp[maxn<<1]

;double

dis(point&a,point&b)

bool

cmp(point&a,point&b)

int n;

double

cdq(

int l,

int r)

}return mindis;

}int

main()

sort

(point+

1,point+

1+n*

2,cmp)

;printf

("%.3f\n"

,cdq(1

,n<<1)

);}return0;

}

平面最近點對問題 分治

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

平面最近點對問題 分治

1 演算法描述 已知集合s中有n個點,一共可以組成n n 1 2對點對,蠻力法就是對這n n 1 2對點對逐對進行距離計算,通過迴圈求得點集中的最近點對 2 演算法時間複雜度 演算法一共要執行 n n 1 2次迴圈,因此演算法複雜度為o n2 實現 利用兩個for迴圈可實現所有點的配對,每次配對算出...

演算法 分治 平面最近點對

給定平面上n個點,找出其中的一對點的距離,使得在這n個點的所有點對中,該距離為所有點對中最小的 將每乙個點按照橫座標排序,然後分治區間 1,n 1,n 1,n 再內乙個遞迴函式內 如下 include using namespace std struct node a 300000 int temp...