HDU4347、The Closest M Points(KDtree模板学习)

The Closest M Points

Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 98304/98304 K (Java/Others)
Total Submission(s): 7469    Accepted Submission(s): 2342


 

Problem 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:


Can you help him solve this problem?

 

 

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

 

 

Author

HIT

 

 

Source

2012 Multi-University Training Contest 5

 

 

Recommend

zhuyuanchen520   |   We have carefully selected several similar problems for you:  4340 4348 4346 4345 4344 

 

 

一、原题地址

点我传送

 

二、大致题意

在K维度的空间里寻找距离给出的点最近的m个点。

 

三、大致思路

第一次用KDtree的板子,准备进京赶考。模板是网上扒拉下来的,仍需做更多的题目理解。

 

四、代码

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<set>
#include<map>
#include<unordered_set>
#include<vector>
using namespace std;
const int inf = 0x3f3f3f3f;
typedef long long LL;
const double eps = 1e-6;



#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;									//idx用以记录属性

struct Node
{
	int feature[5];			//定义属性数组
	bool operator < (const Node &u)const
	{
		return feature[idx] < u.feature[idx];
	}
}_date[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 date[N<<2];		//data[]数组代表K-D树的所有节点数据
		int flag[N << 2];		//用于标记某个节点是否存在,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(_date + l, _date + mid, _date + r + 1);	 //nth_element()为STL中寻找中位数函数
	date[rt] = _date[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, date[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, y = rson;
	if (p.feature[dim] >= date[rt].feature[dim])
		swap(x, y);				//数据p的第dim个特征值大于等于当前的数据,则需要进入右子树
	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] - date[rt].feature[dim]) < Q.top().first)
		{
			fg = 1;
		}
	}
	if (~flag[y] && fg)
		Query(p, m, y, dept + 1);
}


Node ans[20];
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", &_date[i].feature[j]);
		}
		kd.Build(0, n - 1, 1, 0);
		int q;
		scanf("%d", &q);
		while (q--)
		{
			Node que;
			int m;
			for (int i = 0; i < k; i++)
				scanf("%d", &que.feature[i]);
			scanf("%d", &m);
			kd.Query(que, m, 1, 0);
			printf("the closest %d points are:\n", m);
			int cnt = 0;
			while (!Q.empty())
			{
				ans[cnt++] = Q.top().second;
				Q.pop();
				
			}
			for (int i = m - 1; i >= 0; i--)
			{
				for (int j = 0; j < k; j++)
				{
					if (!j)printf("%d", ans[i].feature[j]);
					else printf(" %d", ans[i].feature[j]);
				}
				printf("\n");
			}
		}
	}
	getchar();
	getchar();
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值