1. 程式人生 > >bryce1010專題——KD-Tree

bryce1010專題——KD-Tree

bryce1010專題——KD-Tree

【KD-Tree模板題】
HDU-4347 The Closest M Points
http://acm.hdu.edu.cn/showproblem.php?pid=4347
【題意】
求一個點的最近M個點。
(1=<n<=50000,1=<t<=10000)

【思路】
KD-Tree

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <queue> using namespace std; #define N 50005 #define lson rt << 1 #define rson rt << 1 | 1 #define Pair pair<double, Node> #define Sqrt2(x) (x) * (x) int n, k, idx; struct Node { int feature[5]; //定義屬性陣列 bool operator < (const Node &u) const {
return feature[idx] < u.feature[idx]; } }_data[N]; //_data[]陣列代表輸入的資料 priority_queue<Pair> Q; //佇列Q用於存放離p最近的m個數據 class KDTree{ public: void Build(int, int, int, int); //建樹 void Query(Node, int, int, int); //查詢 private: Node data[4 * N]
; //data[]陣列代表K-D樹的所有節點資料 int flag[4 * N]; //用於標記某個節點是否存在,1表示存在,-1表示不存在 }kd; //建樹步驟,引數dept代表樹的深度 void KDTree::Build(int l, int r, int rt, int dept) { if(l > r) return; flag[rt] = 1; //表示編號為rt的節點存在 flag[lson] = flag[rson] = -1; //當前節點的孩子暫時標記不存在 idx = dept % k; //按照編號為idx的屬性進行劃分 int mid = (l + r) >> 1; nth_element(_data + l, _data + mid, _data + r + 1); //nth_element()為STL中的函式 data[rt] = _data[mid]; Build(l, mid - 1, lson, dept + 1); //遞迴左子樹 Build(mid + 1, r, rson, dept + 1); //遞迴右子樹 } //查詢函式,尋找離p最近的m個特徵屬性 void KDTree::Query(Node p, int m, int rt, int dept) { if(flag[rt] == -1) return; //不存在的節點不遍歷 Pair cur(0, data[rt]); //獲取當前節點的資料和到p的距離 for(int i = 0; i < k; i++) cur.first += Sqrt2(cur.second.feature[i] - p.feature[i]); int dim = dept % k; //跟建樹一樣,這樣能保證相同節點的dim值不變 bool fg = 0; //用於標記是否需要遍歷右子樹 int x = lson; int y = rson; if(p.feature[dim] >= data[rt].feature[dim]) //資料p的第dim個特徵值大於等於當前的資料,則需要進入右子樹 swap(x, y); if(~flag[x]) Query(p, m, x, dept + 1); //如果節點x存在,則進入子樹繼續遍歷 //以下是回溯過程,維護一個優先佇列 if(Q.size() < m) //如果佇列沒有滿,則繼續放入 { Q.push(cur); fg = 1; } else { if(cur.first < Q.top().first) //如果找到更小的距離,則用於替換佇列Q中最大的距離的資料 { Q.pop(); Q.push(cur); } if(Sqrt2(p.feature[dim] - data[rt].feature[dim]) < Q.top().first) { fg = 1; } } if(~flag[y] && fg) Query(p, m, y, dept + 1); } //輸出結果 void Print(Node data) { for(int i = 0; i < k; i++) printf("%d%c", data.feature[i], i == k - 1 ? '\n' : ' '); } int main() { while(scanf("%d%d", &n, &k)!=EOF) { for(int i = 0; i < n; i++) for(int j = 0; j < k; j++) scanf("%d", &_data[i].feature[j]); kd.Build(0, n - 1, 1, 0); int t, m; scanf("%d", &t); while(t--) { Node p; for(int i = 0; i < k; i++) scanf("%d", &p.feature[i]); scanf("%d", &m); while(!Q.empty()) Q.pop(); //事先需要清空優先佇列 kd.Query(p, m, 1, 0); printf("the closest %d points are:\n", m); Node tmp[25]; for(int i = 0; !Q.empty(); i++) { tmp[i] = Q.top().second; Q.pop(); } for(int i = m - 1; i >= 0; i--) Print(tmp[i]); } } return 0; }

【KD-Tree模板】
HDU2966 In case of failure
http://acm.hdu.edu.cn/showproblem.php?pid=2966

【題意】
給n個二維點,求每個點距離其它點最近的距離。

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    
    final static int SIZE = 100005;
	final static double EPS = 1e-10;
    
    private boolean[] d = null;
    private Node[] p = null;
    private long res;
    private int index;
    private int size;
    
    public class Node{
        private long[] x = null;
        Node(){
            x = new long[2];
        }
    }
    
    Main(int size){
        d = new boolean[size];
        p = new Node[size];
        for(int i = 0; i < size; i++)
            p[i] = new Node();
    }

    public void setSize(int size){
        this.size = size;
		Arrays.fill(d, false);
    }
    
    public void clear(){
        res = Long.MAX_VALUE;
        index = 0;
    }
    
    public void Insert(int id, Node t){
        p[id] = t;
    }
    
    public Node get(int id){
        return p[id];
    }

    public void InsertSort(Node a[], int id, int l, int r){
		for(int i = l + 1; i <= r; i++){
			if(a[i - 1].x[id] > a[i].x[id]){
				Node t = new Node();
				t = a[i];
				int j = i;
				while(j > l && a[j - 1].x[id] > t.x[id])
	            {
	                a[j] = a[j - 1];
	                j--;
	            }
	            a[j] = t;
			}
		}
	}
	
	public Node FindMid(Node a[], int id, int l, int r)
	{
	    if(l == r) return a[l];
	    int i = 0;
	    int n = 0;
	    for(i = l; i < r - 5; i += 5)
	    {
	        InsertSort(a, id, i, i + 4);
	        n = i - l;

			Node t = new Node();
			t = a[l + n / 5];
			a[l + n / 5] = a[i + 2];
			a[i + 2] = t;
	    }

	    int num = r - i + 1;
	    if(num > 0)
	    {
	        InsertSort(a, id, i, i + num - 1);
	        n = i - l;

			Node t = new Node();
			t = a[l + n / 5];
            a[l + n / 5] = a[i + num / 2];
			a[i + num / 2] = t;
	    }
	    n /= 5;
	    if(n == l) return a[l];
	    return FindMid(a, id, l, l + n);
	}
	
	public boolean Equals(Node a, Node b){
		if(Math.abs(a.x[0] - b.x[0]) > EPS) 
			return false;
		if(Math.abs(a.x[1] - b.x[1]) > EPS) 
			return false;
		return true;
	}
	
	public int FindId(Node a[], int l, int r, Node num)
	{
	    for(int i = l; i <= r; i++)
	        if(Equals(a[i], num))
	        	return i;
	    return -1;
	}
	
	public int Partion(Node a[], int id, int l, int r, int p)
	{
	    Node t = new Node();
        t = a[p];
		a[p] = a[l];
		a[l] = t;

	    int i = l;
	    int j = r;
	    Node pivot = a[l];
	    while(i < j)
	    {
	        while(a[j].x[id] >= pivot.x[id] && i < j)
	            j--;
	        a[i] = a[j];
	        while(a[i].x[id] <= pivot.x[id] && i < j)
	            i++;
	        a[j] = a[i];
	    }
	    a[i] = pivot;
	    return i;
	}
	
	public Node BFPTR(Node a[], int id, int l, int r, int k)
	{
		if(l > r) return null;
	    Node num = FindMid(a, id, l, r);  
	    int p =  FindId(a, l, r, num); 
	    int i = Partion(a, id, l, r, p);

	    int m = i - l + 1;
	    if(m == k) return a[i];
	    if(m > k)  return BFPTR(a, id, l, i - 1, k);
	    return BFPTR(a, id, i + 1, r, k - m);
	}

    public Node getInterval(Node p[], int id, int l, int r){
        Node t = new Node();
        long max = Long.MIN_VALUE;
        long min = Long.MAX_VALUE;
        for(int i = l; i <= r; i++){
            if(max < p[i].x[id]) max = p[i].x[id];
            if(min > p[i].x[id]) min = p[i].x[id];
        }
        t.x[0] = min;
        t.x[1] = max;
        return t;
    }
    
    public long getDist(Node a, Node b){
        return (a.x[0] - b.x[0]) * (a.x[0] - b.x[0]) + (a.x[1] - b.x[1]) * (a.x[1] - b.x[1]);
    }

    public void Build(Node p[], int l, int r){
        if(l > r) return;
        Node t1 = getInterval(p, 0, l, r);
        long minx = t1.x[0];
        long maxx = t1.x[1];
        
        Node t2 = getInterval
            
           

相關推薦

bryce1010專題——KD-Tree

bryce1010專題——KD-Tree 【KD-Tree模板題】 HDU-4347 The Closest M Points http://acm.hdu.edu.cn/showproblem.php?pid=4347 【題意】 求一個點的最近M個點。 (1=<n<=5

【bzoj1941】[Sdoi2010]Hide and Seek KD-tree

地形 容易 輸入一個整數 坐標 highlight 最小值 水平 簡單 一個點 題目描述 小豬iPig在PKU剛上完了無聊的豬性代數課,天資聰慧的iPig被這門對他來說無比簡單的課弄得非常寂寞,為了消除寂寞感,他決定和他的好朋友giPi(雞皮)玩一個更加寂寞的遊戲---捉

【bzoj2850】巧克力王國 KD-tree

維護 microsoft cor printf ace 但是 urn ans else 題目描述 巧克力王國裏的巧克力都是由牛奶和可可做成的。但是並不是每一塊巧克力都受王國人民的歡迎,因為大家都不喜歡過於甜的巧克力。對於每一塊巧克力,我們設x和y為其牛奶和可可的含量。由於

【BZOJ3489】A simple rmq problem kd-tree

while 長度 {} per tput amp 可能 ans bzoj3489 【BZOJ3489】A simple rmq problem Description 因為是OJ上的題,就簡單點好了。給出一個長度為n的序列,給出M個詢問:在[l,r]之間找到一個在這

【bzoj2989】數列 KD-tree

數據 ++ class microsoft 出現 cpp ros int 所有 題目描述 給定一個長度為n的正整數數列a[i]。 定義2個位置的graze值為兩者位置差與數值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]|。 2種操作(k都是正整

【bzoj4605】嶗山白花蛇草水 權值線段樹套KD-tree

復雜 接下來 efi ora 這也 多少 線段樹 會有 如果 題目描述 神犇Aleph在SDOI Round2前立了一個flag:如果進了省隊,就現場直播喝嶗山白花蛇草水。憑借著神犇Aleph的實力,他輕松地進了山東省省隊,現在便是他履行諾言的時候了。蒟蒻Bob特地為他準

【BZOJ4605】嶗山白花蛇草水 權值線段樹+kd-tree

現在 ive blog 次數 pan std highlight 解釋 pac 【BZOJ4605】嶗山白花蛇草水 Description 神犇Aleph在SDOI Round2前立了一個flag:如果進了省隊,就現場直播喝嶗山白花蛇草水。憑借著神犇Aleph的實力

【BZOJ2626】JZPFAR kd-tree+堆

long long print prior ros strong led queue 整數 cond 【BZOJ2626】JZPFAR Description   平面上有n個點。現在有m次詢問,每次給定一個點(px, py)和一個整數k,輸出n個點中離(px,

【bzoj2626】JZPFAR KD-tree+堆

左右 clu 替換 坐標 元素 util light amp nbsp 題目描述 平面上有n個點。現在有m次詢問,每次給定一個點(px, py)和一個整數k,輸出n個點中離(px, py)的距離第k大的點的標號。如果有兩個(或多個)點距離(px, py)相同,那麽認為

hdu 2966 In case of failure(KD-tree)

-- pri include while failure ref element spl define 題目鏈接:hdu 2966 In case of failure 題意: 給你n個點,讓你輸出每個點到最近點的歐式距離。 題解: KD-樹裸題,板子抄的鳥神的。 1

【模板】超強KD-Tree模板

mem def closed con fin close long 之前 strong 之所以說超強,是因為這個模板又短(我見過最短的kdtree)跑得又快(我用來寫了某道題在vj上跑了第一)也易於修改(之前拿某個大板子來改,不僅不好改而且改了跑得賊慢)。無需初始化任何變量

BZOJ 2648 SJY擺棋子(KD Tree

tor air math space min void php class sta http://www.lydsy.com/JudgeOnline/problem.php?id=2648 題意: 思路: KDtree模板題。 參考自http://www.cn

【learning】kd-tree

應該 原因 處理 math 二叉 。。 答案 dal 添加 吐槽 kd-tree這個東西很早就聽說過了但是qwq一直沒有去了解 (原因的話。。啊哈哈聽說是什麽跟二維平面之類的東西有關的所以就慫掉了qwq沒錯就是慫qwq) 但其實好像。。真的很暴力啊qwq知道思路之後隨便亂搞

【BZOJ1941】Hide and Seek(KD-Tree

hid cstring clu truct amp OS nth href getc 【BZOJ1941】Hide and Seek(KD-Tree) 題面 BZOJ 洛谷 題解 \(KD-Tree\)對於每個點搜一下最近點和最遠點就好了 #include<iostr

kd-tree板子

friend per temp cst return build http com names https://www.lydsy.com/JudgeOnline/problem.php?id=2648 存個kd-tree板子 #include<cstdio&

bryce1010專題訓練——最小費用最大流

bryce1010專題訓練——最小費用最大流 分為: SPFA費用流 zkw費用流 【最小費用最大流+浮點數】 HDU5988 Coding contest https://vjudge.net/problem/HDU-5988 【題意】 給定n個點,

kd-tree找最鄰近點 Python實現

kd-tree找最鄰近點 Python實現 基本概念 kd-tree是KNN演算法的一種實現。演算法的基本思想是用多維空間中的例項點,將空間劃分為多塊,成二叉樹形結構。劃分超矩形上的例項點是樹的非葉子節點,而每個超矩形內部的例項點是葉子結點。 超矩形劃分方法 有資料集data

BZOJ 2648: SJY擺棋子(kd tree)

題目:https://www.lydsy.com/JudgeOnline/problem.php?id=2648 #include<bits/stdc++.h> using namespace std; const int inf = 0x3f3f3f3f; const int

hdu 4347 The Closest M Points (kd tree 模板題)

題目:http://acm.hdu.edu.cn/showproblem.php?pid=4347 #include<bits/stdc++.h> using namespace std; #define sq(x) (x)*(x) const int maxn=6e4+10;

kd-tree 題目練習

kd tree原理詳解: KD-樹介紹 程式碼模板和部分題借鑑:kd-tree小結 例題一: P4475 巧克力王國 思路:根據巧克力a和可可b建立kd-tree,每個節點維護子樹的最大的a,b以及最小的a,b,一個子樹的權值和sum,每次查詢,如果四對極值點 a b滿足 x*a+