最近點對 HDU5721

2021-07-15 15:29:14 字數 1811 閱讀 1905

最近點對:

對所有點按照 x座標排序。然後分治,求出左半邊和右半邊的最近點對,對於兩邊的最近距離取較小的,記為 d。取從分治的中間點向左右各距離為 d d的範圍中的所有點,把這些點按照 y座標排序。對於每個點,掃一下與它 y座標差小於等於 d的點,更新答案,可以證明(證明沒看懂=_=)這樣的點是很少的,不超過6個。

該題題意:給定n個點的座標,第i個點消失後的最近點對距離為di,求di的和。

這題解法: 因為如果消失的點不是最近點對,那麼對答案是沒有影響的。

所以可以先求出沒消失之前的最近點距離*(n-2),(n-2)指的是消失的點不是最近點對。再分別求兩個最近點消失後的最近點距離。

#include 

#include

#include

#include

#include

#define x first

#define y second

using

namespace

std;

typedef

long

long ll;

struct point

p[100005];

int tmp[100005];

int a,b;

ll mn=1ll<<54;

bool cmpxy(point a,point b)

void update(int a,int b)//更新[1,n]的最近點對

}ll closest(int l,int r)

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

ll ret=min(closest(l,mid),closest(mid+1,r));

int k=0;

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

sort(tmp,tmp+k,cmpy);

for(int i=0;ifor(int j=i+1;j1ll*(p[tmp[j]].y-p[tmp[i]].y)*(p[tmp[j]].y-p[tmp[i]].y)<=ret;j++)

return ret;

/*ret為[l,r]區間的最近點距離的d^2,所以前面都是類似這種

(p[mid].x-p[i].x)*(p[mid].x-p[i].x)<=ret

用來表示x座標差小於d

}int main()

{#ifdef local

freopen("in.txt","r",stdin);

#endif // local

int t;

scanf("%d",&t);

while(t--)

{int n;

ll ans=0;

scanf("%d",&n);

for(int i=1;i<=n;i++)

scanf("%d%d",&p[i].x,&p[i].y);

sort(p+1,p+1+n,cmpxy);

closest(1,n);

ans+=mn*(n-2);

mn=1ll<<50;

int a=a,b=b;

for(int i=1;i<=n;i++)

if(i==a) swap(p[i],p[n]);

closest(1,n-1);

ans+=mn;

mn=1ll<<50;

for(int i=1;i<=n;i++)

if(i==b) swap(p[i],p[n]);

closest(1,n-1);

ans+=mn;

mn=1ll<<50;

cout<

hdu1007 最近點對

題意 給你n個點,讓你求最近的兩個點的距離是多少.思路 這個題目我沒思路,我在網上看的是什麼分治 鴿巢原理,分治我知道,鴿巢原理我也知道,但是這個題目就是沒有證明出來他和鴿巢原理有jm關係,總之就是先以x或者y優先sort一下,然後每次列舉每個相鄰點的附近5個就行了 加自己一共六個 而且這個題目的前...

HDU 1007 最近點對

分治法求最近點對 遞迴將點不斷分成小組,計算最短距離。此時的最短距離僅僅是兩點都屬兩塊的某一塊 這裡的分割點是mid點 還需要考慮兩點分屬兩塊的情況。這時對於選點則把範圍縮小到了以mid為中心。再將距離mid點x軸2 mindist範圍點考慮在內。在這些點中,再取mid點,留下那些 y的距離不大於m...

hdu 1007 最近點對

最近點對問題定義 已知上m個點的集合,找出對接近的一對點。在二維空間裡,可用分治法求解最近點對問題。預處理 分別根據點的x軸和y軸座標進行排序,得到x和y,很顯然此時x和y中的點就是s中的點。情況 1 點數小於等於三時 情況 2 點數大於三時 首先劃分集合s為sl和sr,使得sl中的每乙個點位於sr...