平面最近点对【kd树初探】
来源:互联网 发布:教学视频录制软件 编辑:程序博客网 时间:2024/06/03 14:54
Description
给出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
给出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
引用一下http://www.cnblogs.com/snake-hand/archive/2012/08/13/2636236.html
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;}
1 0
- 平面最近点对【kd树初探】
- 利用kd树进行平面内最近点搜索
- 【HDU5721 BestCoder 2nd AnniversaryD】【平面最近点对 分治写法+KD-tree写法】Palace 平面最近点对
- 平面最近点对
- 平面最近点对
- 平面最近点对
- 平面最近点对
- 平面最近点对
- 平面最近点对
- 平面最近点对
- 平面最近点对
- 平面最近点对
- 平面最近点对 转载
- hdu1007 平面最近点对
- POJ_3714_Raid(平面最近点对)
- 平面最近距离点对
- 平面上最近点对
- 平面最近点对问题
- mysql阅读笔记四
- MySQL创建帐号/修改权限不生效
- 函数式treap
- Cmake突然编译什么都不成功 CMake Error at ...CMakeTestCCompiler.cmake:61 (message)
- Android常用界面布局
- 平面最近点对【kd树初探】
- docker运行image相关命令
- uva 10828 高斯消元·dp
- bzoj1024: [SCOI2009]生日快乐
- 指针数组与数组指针
- Rails Json XML Action
- DAO(Data Access Object) 数据访问对象
- Catch That Cow
- oracle数据闪回功能(恢复误删除的表信息)