HDU 5992 Finding Hotels(KD树)题解
题意:n家旅店,每个旅店都有坐标x,y,每晚价钱z,m个客人,坐标x,y,钱c,问你每个客人最近且能住进去(非花最少钱)的旅店,一样近的选排名靠前的。
思路:KD树模板题
代码:
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
typedef long long ll;
const int maxn = + ;
const int seed = ;
const ll MOD = 1e9 + ;
const int INF = 0x3f3f3f3f;
using namespace std; #define lson rt << 1
#define rson rt << 1 | 1
#define Pair pair<ll, Node> int k, idx; //维数k struct Node
{
int feature[]; //定义属性数组
int id;
bool operator < (const Node &u) const
{
return feature[idx] < u.feature[idx];
}
}_data[maxn], p; //_data[]数组代表输入的数据
Node data[ * maxn]; //data[]数组代表K-D树的所有节点数据
int flag[ * maxn]; //用于标记某个节点是否存在,1表示存在,-1表示不存在 priority_queue<Pair> Q; //队列Q用于存放离p最近的m个数据
ll Sqrt(ll a, ll b){ //欧几里得距离平方
return (a - b) * 1LL * (a - b);
} //建树步骤,参数dept代表树的深度
void Build(int l, int r, int rt, int dept)
{
if(l > r) return;
flag[rt] = ; //表示编号为rt的节点存在
flag[lson] = flag[rson] = -; //当前节点的孩子暂时标记不存在
idx = dept % k; //按照编号为idx的属性进行划分
int mid = (l + r) >> ;
nth_element(_data + l, _data + mid, _data + r + ); //nth_element()为STL中的函数 algorithm
data[rt] = _data[mid];
Build(l, mid - , lson, dept + ); //递归左子树
Build(mid + , r, rson, dept + ); //递归右子树
} //查询函数,寻找离p最近的m个特征属性
void Query(Node p, int m, int rt, int dept)
{
if(flag[rt] == -) return; //不存在的节点不遍历
Pair cur(, data[rt]); //获取当前节点的数据和到p的距离
for(int i = ; i < k; i++) //欧几里得距离的平方
cur.first += Sqrt((ll)data[rt].feature[i], (ll)p.feature[i]);
int dim = dept % k; //跟建树一样,这样能保证相同节点的dim值不变
bool fg = ; //用于标记是否需要遍历右子树
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 + ); //如果节点x存在,则进入子树继续遍历 //以下是回溯过程,维护一个优先队列
if(Q.size() < m) //如果队列没有满,则继续放入
{
if(cur.second.feature[] <= p.feature[]) Q.push(cur);
fg = ;
}
else
{
if(cur.first < Q.top().first && cur.second.feature[] <= p.feature[]) //如果找到更小的距离,则用于替换队列Q中最大的距离的数据
{
Q.pop();
Q.push(cur);
}
else if(cur.first == Q.top().first && cur.second.id < Q.top().second.id && cur.second.feature[] <= p.feature[]){
Q.pop();
Q.push(cur);
}
if(Sqrt((ll)p.feature[dim], (ll)data[rt].feature[dim]) < Q.top().first)
{
fg = ;
}
}
if(~flag[y] && fg)
Query(p, m, y, dept + );
}
int main(){
int T, n, m;
k = ;
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
for(int i = ; i < n; i++){
for(int j = ; j < ; j++)
scanf("%d", &_data[i].feature[j]);
_data[i].id = i;
}
Build(, n - , , );
while(m--){
while(!Q.empty()) Q.pop();
for(int i = ; i < ; i++)
scanf("%d", &p.feature[i]);
Query(p, , , );
p = Q.top().second;
printf("%d %d %d\n", p.feature[], p.feature[], p.feature[]);
}
}
return ;
}
模板:
#define lson rt << 1
#define rson rt << 1 | 1
#define Pair pair<ll, Node> int k, idx; //维数k struct Node
{
int feature[]; //定义属性数组
int id;
bool operator < (const Node &u) const
{
return feature[idx] < u.feature[idx];
}
}_data[maxn], p; //_data[]数组代表输入的数据
Node data[ * maxn]; //data[]数组代表K-D树的所有节点数据
int flag[ * maxn]; //用于标记某个节点是否存在,1表示存在,-1表示不存在 priority_queue<Pair> Q; //队列Q用于存放离p最近的m个数据
ll Sqrt(ll a, ll b){ //欧几里得距离平方
return (a - b) * 1LL * (a - b);
} //建树步骤,参数dept代表树的深度
void Build(int l, int r, int rt, int dept)
{
if(l > r) return;
flag[rt] = ; //表示编号为rt的节点存在
flag[lson] = flag[rson] = -; //当前节点的孩子暂时标记不存在
idx = dept % k; //按照编号为idx的属性进行划分
int mid = (l + r) >> ;
nth_element(_data + l, _data + mid, _data + r + ); //nth_element()为STL中的函数 algorithm
data[rt] = _data[mid];
Build(l, mid - , lson, dept + ); //递归左子树
Build(mid + , r, rson, dept + ); //递归右子树
} //查询函数,寻找离p最近的m个特征属性
void Query(Node p, int m, int rt, int dept)
{
if(flag[rt] == -) return; //不存在的节点不遍历
Pair cur(, data[rt]); //获取当前节点的数据和到p的距离
for(int i = ; i < k; i++) //欧几里得距离的平方
cur.first += Sqrt((ll)data[rt].feature[i], (ll)p.feature[i]);
int dim = dept % k; //跟建树一样,这样能保证相同节点的dim值不变
bool fg = ; //用于标记是否需要遍历右子树
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 + ); //如果节点x存在,则进入子树继续遍历 if(Q.size() < m) //如果队列没有满,则继续放入
{ //注意,这里必须让fg=1,以后改时注意
Q.push(cur);
fg = ;
}
else
{
if(cur.first < Q.top().first) //如果找到更小的距离,则用于替换队列Q中最大的距离的数据
{
Q.pop();
Q.push(cur);
}
if(Sqrt((ll)p.feature[dim], (ll)data[rt].feature[dim]) < Q.top().first)
{
fg = ;
}
}
if(~flag[y] && fg)
Query(p, m, y, dept + );
}
HDU 5992 Finding Hotels(KD树)题解的更多相关文章
- HDU 5809 Ants(KD树+并查集)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5809 [题目大意] 给出一些蚂蚁和他们的巢穴,一开始他们会在自己的巢穴(以二维坐标形式给出),之后 ...
- K-D树问题 HDU 4347
K-D树可以看看这个博客写的真心不错!这里存个版 http://blog.csdn.net/zhjchengfeng5/article/details/7855241 HDU 4349 #includ ...
- 2016 ICPC青岛站---k题 Finding Hotels(K-D树)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5992 Problem Description There are N hotels all over ...
- 【HDU5992】Finding Hotels 【KD树】
题意 给出n个酒店的坐标和价格,然后m个查询,每个查询给出一个人的坐标和能承受的最大价格,然后找出在他价格承受范围以内,距离他最近的宾馆,如果有多个,那么输出第一个 分析 kd树的模板题 #inclu ...
- bzoj 3053 HDU 4347 : The Closest M Points kd树
bzoj 3053 HDU 4347 : The Closest M Points kd树 题目大意:求k维空间内某点的前k近的点. 就是一般的kd树,根据实测发现,kd树的两种建树方式,即按照方差 ...
- HDU 6022---MG loves set(K-D树)
题目链接 Problem Description MG is an intelligent boy. One day he was challenged by the famous master ca ...
- hdu 4347 The Closest M Points (kd树)
版权声明:本文为博主原创文章,未经博主允许不得转载. hdu 4347 题意: 求k维空间中离所给点最近的m个点,并按顺序输出 . 解法: kd树模板题 . 不懂kd树的可以先看看这个 . 不多说, ...
- 数据结构(KD树):HDU 4347 The Closest M Points
The Closest M Points Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 98304/98304 K (Java/Ot ...
- hdu 2966 In case of failure k-d树
题目链接 给n个点, 求出每个点到离它最近的点的距离. 直接建k-d树然后查询就可以 感觉十分神奇... 明白了算法原理但是感觉代码还不是很懂... #include <bits/stdc++ ...
随机推荐
- 【python基础】字符串格式化(% VS format)
字符串格式化 Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存. 1.百分号方式 ...
- sass不识别中文字符的问题
进入Koala安装目录,例如:C:\Program Files (x86)\Koala\rubygems\gems\sass-3.4.9\lib\sass 或者 C:\Ruby\lib\ruby\ge ...
- 获取图片的大小(宽高):BytesIO
获取图片的大小(宽高) from io import BytesIO,StringIO import requests from PIL import Image img_url = "ht ...
- 图片放大_css3
.flash_little_img{position:relative;}.flash_little_img{width:500px;height:333px;border:none; margin: ...
- 【剑指offer】斐波那契数列
一.题目: 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项.n<=39 二.思路: 式子: n=0时,f=0:n=1或者n=2时f=1:否则f=f(n-1)+f(n ...
- SparkSQL UDF两种注册方式:udf() 和 register()
调用sqlContext.udf.register() 此时注册的方法 只能在sql()中可见,对DataFrame API不可见 用法:sqlContext.udf.register("m ...
- Pandas之Dropna滤除缺失数据
import pandas as pd import numpy as np from numpy import nan as NaN 一.处理Series对象 通过dropna()滤除缺失数据 fr ...
- selenium webdriver处理浏览器Cookie
有时候我们需要验证浏览器中是否存在某个cookie,因为基于真实的cookie 的测试是无法通过白盒和集成测试完成的.WebDriver 提供了操作Cookie 的相关方法可以读取.添加和删除cook ...
- Oracle获取数据库中的对象创建语句
使用dbms_metadata.get_ddl()函数可以做到. 实验环境:Oracle 11.2.0.4 以获取jingyu用户下的T1表为例: SQL> conn jingyu/jingyu ...
- 171. Excel Sheet Column Number(简单数学题)
Given a column title as appear in an Excel sheet, return its corresponding column number. For exampl ...