p1257 平面上最接近点对---(分治法)
首先就是一维最接近点的情况。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
double s[];
double ans=; int main(){
int n;
while(~scanf("%d",&n)){
for( int i=; i<n; i++ ){
scanf("%lf",s+i);
}
sort(s,s+n);
ans=INF;
for( int i=; i<n; i++ ){
ans=(s[i+]-s[i]>ans)?ans:(s[i+]-s[i]);
}
printf("%f\n",ans); }
return ;
}
很显然这是暴力求解的方法。。。
但是这种方法不适合推移到二维方面,因而推荐使用分治法进行求解没时间复杂度O(nlogn)。。。
使用分治求解:
S中的n个点为x轴上的n个实数x1,x2,...,xn。最接近点对即为这n个实数中相差最小的两个实数。显然可以先将点排好序,然后线性扫描就可以了(上述程序实现)。但我们为了便于推广到二维的情形,为下面二维,尝试用分治法解决这个问题。
假设我们用m点将S分为S1和S2两个集合,这样一来,对于所有的p(S1中的点)和q(S2中的点),有p<q。
递归地在S1和S2上找出其最接近点对{p1,p2}和{q1,q2},并设
d = min{ |p1-p2| , |q1-q2| }
由此易知,S中最接近点对或者是{p1,p2},或者是{q1,q2},或者是某个{q3,p3},如下图所示。

如果最接近点对是{q3,p3},即|p3-q3|<d,则p3和q3两者与m的距离都不超过d,且在区间(m-d,d]和(d,m+d]各有且仅有一个点。这样,就可以在线性时间内实现合并。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
double s[];
double ans=; double closest(int low,int high){
if(low+==high) return s[high]-s[low];
if(low+==high) return min(s[low+]-s[low],s[high]-s[low+]);
int mid=(low+high)>>;
double tmp=min(closest(low,mid),closest(mid+,high));
if(s[mid+]-s[mid]<tmp) tmp=s[mid+]-s[mid];
return tmp;
} int main(){
int n,m;
srand((unsigned)time(NULL));
while(~scanf("%d",&n)){
for( int i=; i<n; i++ ){
s[i]=rand()%;
printf("%f",s[i]);
}
printf("\n");
sort(s,s+n);
for( int i=; i<n; i++ ){
printf("%f ",s[i]);
}
printf("\n");
printf("%.4f\n",closest(,n-));
}
return ;
}
接下来二为最接近点对的情况。。。
分治:
1) 把它分成两个或多个更小的问题;
2) 分别解决每个小问题;
3) 把各小问题的解答组合起来,即可得到原问题的解答。小问题通常与原问题相似,可以递归地使用分而治之策略来解决。
其实,这里 用到了分治的思想。将所给平面上n个点的集合S分成两个子集S1和S2,每个子集中约有n/2个点。然后在每个子集中递归地求最接近的点对。在这里,一个 关键的问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对。如果这两个点分别在S1和S2中,问题就变得复 杂了。
在二维的情况下:
我们仿照一维的情况先把所有点按照x(横坐标)从左到右升序排列.
以X横坐标中间的点作为分界线.将平面的点分成左边和右边,以上图为例,分为左边5个右边5个.
然后找到左边的点中最近点对的距离d1,和右边最近点对的距离d2。
令d=min{d1,d2}.那么d是当前整个平面的最近点对的距离吗?
答案不是!!
当前的d1,d2都是两边各自的点的最近距离,但是没有考虑到两边的点相互配对的情况,即是点对一个在左边区域,一个在右边区域.
如果我们这个时候把两边相互配对的所有情况全部罗列出来那么时间复杂度就变为第一种方法的O(n2).
这个时候我们便可以用上面找到的d来限制配对.即是明显超过d的两点不需要配对.如下:
那么在范围内的只有三个点,也就是说只有这个三个点相互配对的距离才可能比d小.那么再按照方法一一样在这些点中找到最短距离再跟d去比较.小的就是当前整个平面中所考虑的所有点中最近点对的距离。
然而在以上问题处理上,有一个问题尚未解决就是如何找到两边区域中的最近点对的距离d1,d2 ?
我们可以发现在处理上面这个问题的时候,和最开始处理所有平面的点最近点距离的问题类似,只是点的数目减半了.
那么我们可以递归以上问题.直到划分的区域中只有二个或者三个点.这样,该区域的最近点对距离就是对应的距离。这也是递归终止的条件。
#include<iostream>
#include<cstdio>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=1e4+; struct point {
double x,y;
}p[maxn];
int a[maxn]; bool cmpx(point a,point b){
return a.x<b.x;
} bool cmpy(int a,int b){
return p[a].y<p[b].y;
} double dis(point a,point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
} double closest(int low,int high){
if(low+==high) return dis(p[low],p[high]);
if(low+==high) return min(dis(p[low],p[high]),min(dis(p[low],p[low+]),dis(p[low+],p[high]))); int mid=(low+high)>>;
double ans=min(closest(low,mid),closest(mid+,high)); int cnt=;
for( int i=low; i<=high; i++ ){
if(p[i].x>=p[mid].x-ans&&p[i].x<=p[mid].x+ans){
a[cnt++]=i;
}
}
sort(a,a+cnt,cmpy);
for( int i=; i<cnt; i++ ){
for( int j=i+; j<cnt; j++ ){
if(p[a[j]].y-p[a[i]].y>=ans) break;
ans=min(ans,dis(p[a[j]],p[a[i]]));
}
}
return ans;
} int main(){
int n;
while(~scanf("%d",&n)){
for( int i=; i<n; i++ ){
scanf("%lf%lf",&p[i].x,&p[i].y);
}
sort(p,p+n,cmpx); printf("%.4f\n",closest(,n-));
}
return ;
}
p1257 平面上最接近点对---(分治法)的更多相关文章
- 洛谷 P1257 平面上的最接近点对 题解
P1257 平面上的最接近点对 题目描述 给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的. 输入格式 第一行:n:2≤n≤10000 接下来n行:每行两 ...
- Luogu P1257 平面上的最接近点对_暴力
这道题数据不大 两点距离用勾股定理求 #include<iostream> #include<cmath> using namespace std; struct node{ ...
- Luogu P1257 平面上的最接近点对 暴力
这道题数据不大 两点距离用勾股定理求 #include<iostream> #include<cmath> using namespace std; struct node{ ...
- 洛谷P1257 平面上的最接近点对
n<=10000个点,求欧几里德距离最小的一对点. 经典分治,把这些点按x排序,分成两半,每边分别算答案,答案是左边的最小,右边的最小,左右组起来的最小三者的最小.发现只有左右组的有点难写. 假 ...
- P1257 平面上的最接近点对
题目描述 给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的 输入输出格式 输入格式: 第一行:n:2≤n≤200000 接下来n行:每行两个实数:x y, ...
- uva10245-The Closest Pair Problem(平面上的点分治)
解析:平面上的点分治,先递归得到左右子区间的最小值d,再处理改区间,肯定不会考虑哪些距离已经大于d的点对,对y坐标归并排序,然后从小到大开始枚举更新d,对于某个点,x轴方向只用考虑[x-d,x+d]( ...
- POJ C程序设计进阶 编程题#4:寻找平面上的极大点
编程题#4:寻找平面上的极大点 来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 65536kB 描 ...
- COJN 0485 800503寻找平面上的极大点
800503寻找平面上的极大点 难度级别:C: 运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 在一个平面上,如果有两个点(x,y),(a,b) ...
- 平面上的地图搜索--Java学习笔记(四)
版权声明: 本文由Faye_Zuo发布于http://www.cnblogs.com/zuofeiyi/, 本文可以被全部的转载或者部分使用,但请注明出处. 这一个月以来,都在学习平面上的地图搜索,主 ...
随机推荐
- IISExpress使用64位
C#有一些函数如GetHashCode和x86,X64版本有关系,为了和服务器保持一致,本地iis Express也需要设置64位. 方法如下,vs2010不支持. vs2012可以手动添加配置 re ...
- Python包中__init__.py作用
在创建python包的过程中,IDE都会在包根目录下创建一个__init__.py文件,该Python文件默认是空的.目录结构如下: Pycharm下的package树结构: 在Finder中的目录结 ...
- H5取经之路——随便写点儿
[相对定位] * 1.使用position:relative:设置元素为相对定位的元素: * 2.定位机制: ①相对于自己原来文档流中的的位置定位,当不指定top等定位值时,不会改变元素位置: ②相对 ...
- 练习:javascript分享划过简单效果
利用目标点判断速度speed正负值.利用目标点函数封装传参, <!doctype html> <html lang="en"> <head> & ...
- 第29月第2天 charles
1. https://www.jianshu.com/p/55a8c84e0f24
- Android WebView重定向问题的解决方案
当WebView在加载网页时,有时会有重定向问题,返回键回退怎么也回退不掉,怎么办? WebView有一个getHitTestResult():返回的是一个HitTestResult,一般会根据打开的 ...
- Saltstack自动化操作记录(2)-配置使用
之前梳理了Saltstack自动化操作记录(1)-环境部署,下面说说saltstack配置及模块使用: 为了试验效果,再追加一台被控制端minion机器192.168.1.118需要在master控制 ...
- Docker: repository, image, container
1. 查看image: docker images 2. 查看信息: docker info 3. 搜索image: docker search [image_name], 比如: docker se ...
- JdbcTemplate中queryForObject方法返回空结果或不正确结果数量的解决方法
在使用Spirng提供的JdbcTemplate中名为queryForObject API进行数据库查询时有时会抛出如下异常: org.springframework.dao.EmptyResultD ...
- PHP生成HTML文件, SummerHtml
2018-6-27 20:13:04 星期三 作用: 用PHP生成HTML文档, 支持标签嵌套缩进 起因: 这个东西确实也是心血来潮写的, 我很满意里边的实现缩进的机制, 大家有用到的可以看看 现在都 ...