平面最近點對

2022-05-26 02:24:09 字數 3416 閱讀 7611

一,平面最近點對

問題:在給n個平面上的點,讓你找到最近的一對點。

暴力n*n做法肯定超時。

我們考慮分治。

1-n這個區間,我們可以先找到a=(1-mid)和b=(mid+1,n)這個區間的最小點對。並一直遞迴下去。

現在主要的問題,在於如何對這兩個區間進行合併操作。

因為,也許最近點對是a區間乙個點b區間乙個點。

我們可以繼續考慮

合併這兩個區間,我們有必要把這兩個區間所有的點都拿來比較一下嗎?

肯定是沒有必要的。

假如當前所求的最小距離為minx,同時我們可以把a[mid]作為乙個旗標。

a區間和b區間的點離旗標之間的距離如果大於minx。那我肯定就不用考慮了。

所以我們合併的時候要考慮的x範圍是[a[mid] - minx,a[mid] + minx]。超過這個範圍的x,距離一定會比minx大。

可是這樣還不夠,萬一所考慮的區間很多點,那複雜度還是降不下來。

我們用考慮x的想法繼續去考慮y。

對於乙個點a的y來說,與點a的最近點b的y,一定不會離a的y差minx距離。

所以我們用這種方法可以把所考慮到的點降低到只有7個點。

為什麼是7個點呢?

可看下面這篇證明:

參考部落格: 大佬的**很好懂了。

例題一:

這題是裸題,可以做模板了。(逃,巨弱還是錯了n次,痛

#include"

stdio.h

"#include

"string.h

"#include

"vector

"#include

"math.h

"#include

"algorithm

"using

namespace

std;

typedef

struct

nodenode;

intn;

node node[

200100

];node tran[

200100

];double minx =1e20;

bool same(double a, double b)

intcmpx(node a,node b)

intcmpy(node a,node b)

void

dist_minx(node a,node b)

void merge_node(int l,int mid,intr)

else

}while(i <= mid) tran[++ t] = node[i ++];

while(j <= r) tran[++ t] = node[j ++];

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

node[i] = tran[i - l + 1];}

void blocking(int l,int

r) }

sort(node + l,node + r + 1

,cmpy);

return

; }

int mid = (l + r) >> 1

;

double midx =node[mid].x;

blocking(l,mid); blocking(mid + 1

,r);

merge_node(l,mid,r);

vector

q;

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

q.push_back(node[i]);

}q.clear();

return;}

intmain()

sort(node + 1,node + n + 1

,cmpx);

blocking(

1,n);

printf(

"%0.4lf\n

",minx);

}

例題二:

題意是要我們找到一對點:類似於最近點對的sqrt((xi+xj)^2 +(yi+yj)^2)使其值最小的點對。

觀察可得,這個式子是不是跟兩點間的距離就只差了乙個符號。

那我們可以把式子轉化為:sqrt((xi-(-xj))^2 +(yi-(-yj))^2)

在根據題意,乙個點可以自由轉化為帶負數的形式。就可做了。

吐了,cmpx寫錯導致浪費了3個小時。

注意:你不能直接在求路徑的時候加負數。這會導致你的y排序不滿足的問題。

所以,我們應該在最後的時候在把k轉換過來。

#include"stdio.h"

#include"string.h"

#include"vector"

#include#include"math.h"

#include"algorithm"

using namespace std;

typedef long long ll;

typedef struct nodenode;

int n;

node node[800100];

node tran[800100];

ll minx = long_long_max;

int v1,v2,s1,s2;

int cmpx(node a,node b) return ;

}void merge_node(int l,int mid,int r)

else

}while(i <= mid) tran[++ t] = node[i ++];

while(j <= r) tran[++ t] = node[j ++];

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

node[i] = tran[i - l + 1];

}void blocking(int l,int r)

}sort(node + l,node + r + 1,cmpy);

return ;

}int mid = (l + r) >> 1;

ll midx = node[mid].x;

blocking(l,mid); blocking(mid + 1,r);

merge_node(l,mid,r);

vectorq;

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

q.push_back(node[i]);

}q.clear();

return ;

}int main()

n = n * 4;

sort(node + 1,node + n + 1,cmpx);

blocking(1,n);

printf("%d %d %d %d\n",v1,s1,v2,5 - s2);

}

平面最近點對

求點集中的最近點對有以下兩種方法 設p1 x1,y1 p2 x2,y2 pn xn,yn 是平面上n個點構成的集合s,設計演算法找出集合s中距離最近的點對。1 蠻力法 適用於點的數目比較小的情況下 1 演算法描述 已知集合s中有n個點,一共可以組成n n 1 2對點對,蠻力法就是對這n n 1 2 ...

平面最近點對

求點集中的最近點對有以下兩種方法 設p1 x1,y1 p2 x2,y2 pn xn,yn 是平面上n個點構成的集合s,設計演算法找出集合s中距離最近的點對。1 蠻力法 適用於點的數目比較小的情況下 1 演算法描述 已知集合s中有n個點,一共可以組成n n 1 2對點對,蠻力法就是對這n n 1 2對...

平面最近點對

求點集中的最近點對有以下兩種方法 設p1 x1,y1 p2 x2,y2 pn xn,yn 是平面上n個點構成的集合s,設計演算法找出集合s中距離最近的點對。1 蠻力法 適用於點的數目比較小的情況下 1 演算法描述 已知集合s中有n個點,一共可以組成n n 1 2對點對,蠻力法就是對這n n 1 2對...