BZOJ3053:The Closest M Points(K-D Teee)

本文介绍了一个基于K-D Tree实现的多维空间中寻找给定点最近邻点的算法。该算法能够处理多达50,000个点,并在K维空间内找出与给定点最近的m个点。通过使用优先队列和递归查询的方式,实现了高效的最近邻搜索。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

The course of Software Design and Development Practice is objectionable. ZLC is facing a serious problem .There are many points in K-dimensional space .Given a point. ZLC need to find out the closest m points. Euclidean distance is used as the distance metric between two points. The Euclidean distance between points p and q is the length of the line segment connecting them.In Cartesian coordinates, if p = (p1, p2,..., pn) and q = (q1, q2,..., qn) are two points in Euclidean n-space, then the distance from p to q, or from q to p is given by:
D(p,q)=D(q,p)=sqrt((q1-p1)^2+(q2-p2)^2+(q3-p3)^2…+(qn-pn)^2
Can you help him solve this problem?


软工学院的课程很讨厌!ZLC同志遇到了一个头疼的问题:在K维空间里面有许多的点,对于某些给定的点,ZLC需要找到和它最近的m个点。

(这里的距离指的是欧几里得距离:D(p, q) = D(q, p) =  sqrt((q1 - p1) ^ 2 + (q2 - p2) ^ 2 + (q3 - p3) ^ 2 + ... + (qn - pn) ^ 2)

ZLC要去打Dota,所以就麻烦你帮忙解决一下了……

【Input】

第一行,两个非负整数:点数n(1 <= n <= 50000),和维度数k(1 <= k <= 5)。
接下来的n行,每行k个整数,代表一个点的坐标。
接下来一个正整数:给定的询问数量t(1 <= t <= 10000)
下面2*t行:
  第一行,k个整数:给定点的坐标
  第二行:查询最近的m个点(1 <= m <= 10)

所有坐标的绝对值不超过10000。
有多组数据!

【Output】

对于每个询问,输出m+1行:
第一行:"the closest m points are:" m为查询中的m
接下来m行每行代表一个点,按照从近到远排序。

保证方案唯一,下面这种情况不会出现:
2 2
1 1
3 3
1
2 2
1

Input

In the first line of the text file .there are two non-negative integers n and K. They denote respectively: the number of points, 1 <= n <= 50000, and the number of Dimensions,1 <= K <= 5. In each of the following n lines there is written k integers, representing the coordinates of a point. This followed by a line with one positive integer t, representing the number of queries,1 <= t <=10000.each query contains two lines. The k integers in the first line represent the given point. In the second line, there is one integer m, the number of closest points you should find,1 <= m <=10. The absolute value of all the coordinates will not be more than 10000.
There are multiple test cases. Process to end of file.

Output

For each query, output m+1 lines:
The first line saying :”the closest m points are:” where m is the number of the points.
The following m lines representing m points ,in accordance with the order from near to far
It is guaranteed that the answer can only be formed in one ways. The distances from the given point to all the nearest m+1 points are different. That means input like this:
2 2
1 1
3 3
1
2 2
1
will not exist.

Sample Input

3 2
1 1
1 3
3 4
2
2 3
2
2 3
1

Sample Output

the closest 2 points are:
1 3
3 4
the closest 1 points are:
1 3

Solution

还是K-D Tree模板,不过这个是真正的多维KDT,做的时候把原来的0/1扩展到多维就好了

查询m远的时候开个大根堆,当答案小于堆顶的时候就push进去,然后query内部稍微改一下

因为query的时候lans和rans忘了赋初值调了半天emmm……

Code

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<queue>
  6 #include<algorithm>
  7 #define N (50000+1000)
  8 #define INF 1e16
  9 using namespace std;
 10 
 11 struct P
 12 {
 13     long long dis,num;
 14     bool operator < (const P &a) const {return dis<a.dis;}
 15 }po;
 16 long long n,k,D,t,Root,m,ans[N];
 17 priority_queue<P>q;
 18 
 19 struct Node
 20 {
 21     long long Max[5],Min[5],d[5],lson,rson;
 22     bool operator < (const Node &a) const {return d[D]<a.d[D];}
 23 }p[N],T;
 24 
 25 struct KDT
 26 {
 27     Node Tree[N];
 28     long long sqr(long long x){return x*x;}
 29 
 30     void Update(long long now)
 31     {
 32         for (int i=0;i<k; ++i)
 33         {
 34             long long ls=Tree[now].lson, rs=Tree[now].rson;
 35             Tree[now].Max[i]=Tree[now].Min[i]=Tree[now].d[i];
 36             if (ls)
 37             {
 38                 Tree[now].Max[i]=max(Tree[now].Max[i],Tree[ls].Max[i]);
 39                 Tree[now].Min[i]=min(Tree[now].Min[i],Tree[ls].Min[i]);
 40             }
 41             if (rs)
 42             {
 43                 Tree[now].Max[i]=max(Tree[now].Max[i],Tree[rs].Max[i]);
 44                 Tree[now].Min[i]=min(Tree[now].Min[i],Tree[rs].Min[i]);
 45             }
 46         }
 47     }
 48     long long Build(long long opt,long long l,long long r)
 49     {
 50         if (l>r) return 0;
 51         long long mid=(l+r)>>1;
 52         D=opt; nth_element(p+l,p+mid,p+r+1);
 53         Tree[mid]=p[mid];
 54         Tree[mid].lson=Build((opt+1)%k,l,mid-1);
 55         Tree[mid].rson=Build((opt+1)%k,mid+1,r);
 56         Update(mid); return mid;
 57     }
 58     long long Get_min(long long now)
 59     {
 60         long long ans=0;
 61         for (int i=0; i<k; ++i)
 62         {
 63             if (T.d[i]>Tree[now].Max[i]) ans+=sqr(T.d[i]-Tree[now].Max[i]);
 64             if (T.d[i]<Tree[now].Min[i]) ans+=sqr(Tree[now].Min[i]-T.d[i]);
 65         }
 66         return ans;
 67     }
 68     void Query(int now)
 69     {
 70         long long ls=Tree[now].lson, rs=Tree[now].rson, lans=INF,rans=INF;
 71         if (ls) lans=Get_min(ls);
 72         if (rs) rans=Get_min(rs);
 73         
 74         long long dist=0;
 75         for (int i=0; i<k; ++i)
 76             dist+=sqr(Tree[now].d[i]-T.d[i]);
 77         po.dis=dist; po.num=now; 
 78         if (dist<q.top().dis)
 79             q.pop(),q.push(po);
 80             
 81         if (lans<rans)
 82         {
 83             if (lans<q.top().dis) Query(ls);
 84             if (rans<q.top().dis) Query(rs);
 85         }
 86         else
 87         {
 88             if (rans<q.top().dis) Query(rs);
 89             if (lans<q.top().dis) Query(ls);
 90         }
 91     }
 92     
 93 }KDT;
 94 
 95 int main()
 96 {
 97     while (scanf("%lld%lld",&n,&k)!=EOF)
 98     {
 99         for (int i=1; i<=n;++i)
100             for (int j=0; j<k; ++j)
101                 scanf("%lld",&p[i].d[j]);
102         Root=KDT.Build(0,1,n);
103         
104         scanf("%lld",&t);
105         for (int i=1; i<=t; ++i)
106         {
107             for (int j=0; j<k; ++j)
108                 scanf("%lld",&T.d[j]);
109             scanf("%lld",&m);
110             for (int i=1; i<=m; ++i)
111             {
112                 po.dis=INF; po.num=0;
113                 q.push(po);
114             }
115             KDT.Query(Root);
116             
117             for (int i=1; i<=m; ++i)
118                 ans[i]=q.top().num,q.pop();
119             printf("the closest %lld points are:\n",m);
120             for (int i=m; i>=1; --i)
121             {
122                 for (int j=0; j<k; ++j)
123                     printf("%lld ",p[ans[i]].d[j]);
124                 printf("\n");
125             }
126         }
127     }
128 }

转载于:https://www.cnblogs.com/refun/p/9303084.html

电动汽车数据集 该综合数据集包含许多品牌和年份的电动汽车和插电式车型的记录,捕获了技术规格、性能、定价、制造原产地、销售和安全相关属性。每一行代表由Vehicle_ID标识的唯一车辆列表。 主要特征 覆盖范围:全球制造商和车型组合,包括纯电动汽车和插电式混合动力汽车。 范围:电池化学成分、容量、续航里程、充电标准和速度、价格、产地、自主水平、排放、安全等级、销售和保修。 时间跨度:模型跨越多个年份(旧版和即将推出的)。 数据质量说明: 某些行的某些字段可能缺失(空白)。 多个分类字段包含不同的特定于供应商的值(例如,Charging_Type、Battery_Type)。 单位在列之间混合;注意千瓦时、公里、小时、美元、克/公里和额定等级。 列 Vehicle_ID 每个车辆记录的唯一标识符。 制造者 车辆品牌或 OEM。 型 年 Battery_Type 使用的电池化学/技术 Battery_Capacity_kWh 标称电池容量(以千瓦时为单位)。 Range_km 充满电后声称的行驶里程(公里)。 Charging_Type 主要的充电接口或功能。 Charge_Time_hr 大致充电时间(小时),上下文因充电方法而异 Price_USD 以美元为单位的指示性车辆价格。 颜色 Country_of_Manufacture 车辆制造/组装的国家/地区。 Autonomous_Level 自动化能力级别(例如,0-5),可能包括子级别的小数。 CO2_Emissions_g_per_km 尾气二氧化碳排放量(以克/公里为单位)(纯电动汽车通常为 0) Safety_Rating 安全等级 Units_Sold_2024 在 2024 年售出的单位 Warranty_Years 保修期(以年为单位)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值