平面最近點對【kd樹初探】
給出n個點,每個點座標為(xi,yi)。
定義距離為D(A,B)=|xA-xB|+|yA-yB|
求每個點到離它最近的點的距離
Input
第一行為一個整數N
接下來N行每行兩個整數xi,yi,表示第i個點的座標
Output
輸出N行,每一行為第i個點的最近距離
Sample Input
4
0 0
0 1
1 0
1 1
Sample Output
1
1
1
1
Range
20% 0<N<1001
100% 0<N<200001,0<xi,yi<10,000,001
k-d樹可以對k維空間進行劃分。
這裡我們只討論2維情況,多維的思想類似,實現起來也相差無幾。
每次選取一維(最好和之前的維度不同),找到它的中位數,以它為分割線把平面分割成2部分。
然後nth_element()一下,使對於當前維度左邊都是比mid值小的,右邊大的。
然後就遞迴
查詢的時候要注意,以最近點對為例,
假設由一條豎直的線 . | 目標點在左邊,先遞迴左邊找到最近距離S,目標點當前維度座標+S >分割線,說明右邊可能會有一個點使得答案更優。
另外一邊同理!
然後,就這道題而言,每個點離它最近的肯定是本身。就找離他最近的2個點,除去本身就是離它最近的點了!
在細節處理上有需要注意的地方,詳情參考程式碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<cmath> #include<cstring> #include<cstdlib> using namespace std; const int maxn=200000+20; const int maxk=5; int which,K; int n; int m;//平面最近m個點 struct Point { int x[maxk]; bool operator<(const Point &p)const { return x[which]<p.x[which]; } }x[maxn],aim,pr[maxn]; priority_queue<int>q;//儲存最近距離 int ans[5]; int dis(const Point &a,const Point &b) { int len=0; for(int i=0;i<K;i++)len+=abs(a.x[i]-b.x[i]); return len; } void build(int l,int r,int dep) { if(l>r)return ; int mid=(l+r)>>1; which=dep%K; nth_element(x+l,x+mid,x+r+1); build(l,mid-1,dep+1); build(mid+1,r,dep+1); } void query(int l,int r,int dep) { if(l>r)return ; int mid=(l+r)>>1,loc=dep%K; int len=dis(x[mid],aim); if(q.size()<m)q.push(len); else if(len<q.top()){q.pop();q.push(len);} if(l<r) { if(aim.x[loc]<x[mid].x[loc]) { query(l,mid-1,dep+1); if(q.size()<m||aim.x[loc]+q.top()>x[mid].x[loc])query(mid+1,r,dep+1); } else { query(mid+1,r,dep+1); if(q.size()<m||aim.x[loc]-q.top()<x[mid].x[loc])query(l,mid-1,dep+1); } } } int main() { freopen("find.in","r",stdin); freopen("find.out","w",stdout); //轉化為求平面最近2個點 K=2; scanf("%d",&n); for(int i=0;i<n;i++) { for(int j=0;j<K;j++)scanf("%d",&x[i].x[j]); pr[i]=x[i]; } build(0,n-1,0); for(int t=0;t<n;t++) { for(int i=0;i<K;i++)aim.x[i]=pr[t].x[i];//x被重新排了序,所以造成了混亂,應該用之前的x //所以另外開個陣列儲存 m=2; while(!q.empty())q.pop(); query(0,n-1,0); int cnt=0; while(!q.empty()) { ans[cnt++]=q.top(); q.pop(); } printf("%d\n",ans[0]); } return 0; }
相關推薦
平面最近點對【kd樹初探】
Description 給出n個點,每個點座標為(xi,yi)。 定義距離為D(A,B)=|xA-xB|+|yA-yB| 求每個點到離它最近的點的距離 Input 第一
[XSY 1145] 網絡戰爭 平面最近點對 最小割樹
val int tor else sum add name get tar 碼農題. LEN 開到 1000 比較穩. 1 #include <cstdio> 2 #include <cstring> 3 #include &l
牛客練習賽11 B trie樹+拓撲判環 E 分治求平面最近點對
define ima 字典序 父親 name return 如果 int body 牛客練習賽11 B 假的字符串題意:給定n個字符串,互不相等,你可以任意指定字符之間的大小關系(即重定義字典序),求有多少個串可能成為字典序最小的串,並輸出它們。 tags:好題 對
【題解】平面最近點對(加強版)
double clas .org ace gpo bits scanf 簡單 name 洛谷P1429 很久以前就見過並想做的一道題…… 但大概是那個時候太蒻竟然一直不敢做呢,想想時間真的過得好快,從寫‘Hello World’到如今,其實也不過是短短的一個學期呀。 這道題
【POJ3714】Raid:平面最近點對
Description After successive failures in the battles against the Union, the Empire retreated to its last stronghold. Depending on its powerful defense sys
【HDU1007】Quoit Design(分治求平面最近點對)
假設當前區間為[l,r] 中間點為mid 那麼最近點對 要麼在[1,l]中,要麼在[l+1,r]中,要麼兩邊各有一個 我們遞迴處理出左區間的 最近點對距離d1 右區間d2 取d=min(d1,d2) 然後有兩個剪枝來處理情況3 1.按x為關鍵字排個序,列舉[l,r]的點,假如一個點的x與中間點的x差值已經超過
BZOJ 4520 [Cqoi2016]K遠點對(KD樹)
font www tdi 進行 修改 距離 [1] ons blank 【題目鏈接】 http://www.lydsy.com/JudgeOnline/problem.php?id=4520 【題目大意】 求K遠點對距離 【題解】 修改估價
平面最近點對問題
ctype 但是 sof 算法 ans 之間 stream ant logs 平面最近點對問題正如其名,給定平面上的$n$個點,找出其中的一對點,使得這對點的距離在所有點對中最小。 首先顯而易見地我們可以得到這個問題的$O(n^2)$算法,枚舉所有點對即可。但是很顯然我
Luogu 1429 平面最近點對 | 平面分治
www poi alt spa fine 左右 str orm 修改 Luogu 1429 平面最近點對 題目描述 給定平面上n個點,找出其中的一對點的距離,使得在這n個點的所有點對中,該距離為所有點對中最小的 輸入輸出格式 輸入格式: 第一行:n;2≤n≤200000
HDU - 1007 平面最近點對
可能 eat use pla 合並 ase coord int largest Have you ever played quoit in a playground? Quoit is a game in which flat rings are pitched at so
平面最近點對(加強版)
可能 一個 stream opera turn names main 中一 int 傳送門 ovo原來簡單版的非常的好做,只要肆意暴力枚舉即可。 不過這道題的數據範圍變成了200000,即使是洛谷神機也跑不過去的。 於是乎我們考慮分治法。 對於一個平面上的所有點,我們設其屬
POJ3714:求平面最近點對
mes == pre print pan 尋找 int nod cst 尋找兩個集合中的點的最近點對 1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #inc
「LuoguP1429」 平面最近點對(加強版)
urn dig tchar return article ron sdi nbsp git 題目描述 給定平面上n個點,找出其中的一對點的距離,使得在這n個點的所有點對中,該距離為所有點對中最小的 輸入輸出格式 輸入格式: 第一行:n;2≤n≤200
平面最近點對-分治
space name amp point syn cin std 很多 lin n2的暴力就算了。。 我們直接考慮怎樣優化: 我們考慮到可以先按x排序,然後分治,先分別求解兩個子問題。 假設我們已經求得了兩個子問題的答案。 那麽如果合並時,答案能夠更新,當且僅當兩個子區間中
Luogu P1429 平面最近點對(加強版)
P1429 平面最近點對(加強版) 題意 題目描述 給定平面上\(n\)個點,找出其中的一對點的距離,使得在這\(n\)個點的所有點對中,該距離為所有點對中最小的。 輸入輸出格式 輸入格式: 第一行:\(n\);\(2\leq n\leq 200000\) 接下來\(n\)行:每行兩個實數:\(
p1429 平面最近點對
題意:給平面n個點,求最近的兩個點的距離。 思路:運用分治思想,對於n個點,可以分成T(n/2)+T(n/2)的規模,分界線是x座標的中位數, 假設左邊點集合為s1, 右邊點集合為s2,那麼最小值存在於以下三種情況中。 1.s1中任意兩點距離的最小距離 2.s2中任意兩點距離的最
平面最近點對(分治)
一個 分治 ring 輸入輸出格式 class double amp include 最短 題目描述 給定平面上n個點,找出其中的一對點的距離,使得在這n個點的所有點對中,該距離為所有點對中最小的 輸入輸出格式 輸入格式: 第一行:n;2≤n≤20
分治法求平面最近點對
題意 Here 思考 之前考分治的時候有一道題,要用到 \(O(nlogn)\) 求平面最近點對,然而當時我不會……現在寫篇部落格回顧一下。 平面上 \(n\) 個點,讓我們求最近點對,最樸素的想法是列舉,複雜度 \(O(n^2)\) 這樣是顯然過不了 \(1e5\) 的資料的,同時我們也發現對於一
平面最近點對(nlogn)
#include <bits/stdc++.h> using namespace std; const int N = 2e5+1000; struct P{ double x, y; //此處修改int bool operator <(P B)cons
POJ平面最近點對
描述 二維平面上有N個點,求最近點對之間的距離。 輸入第一行一個整數T,表示有T組測試資料每組測試資料第一行一個整數N(2<=N<=1e5)表示平面有N個點接下來有N行,每行兩個整數X Y(-1e9<=X,Y <=1e9)表示點的座標輸出輸出最近點對的距離,精確到小數點後6位樣例輸