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/, 本文可以被全部的转载或者部分使用,但请注明出处. 这一个月以来,都在学习平面上的地图搜索,主 ...
随机推荐
- LINUX 常用命令(一)
1.LINUX系统常用命令实例: A0 LINUX命令分内置命令和非内置命令! 一般而言,内置命令就是指在/bin ./usr/bin下系统默认的命令! 非内置命令需要加上命令的绝对路径执行!比如我们 ...
- python3中的socket
socket是什么?用它做什么? socket,我们通俗的称之为套接字, 是进程间通信的一种方式,但是他与其他进程通信的一个主要区别是 他能实现不同主机间的通信,比如我们现在用的浏览器,在比如我们使用 ...
- Delete from join 用法
delete (别名) from tblA (别名) left join tblb (别名) on...用法 1.创建使用的表及数据 CREATE TABLE YSHA ( code ), NAME ...
- JAVA进阶12
间歇性混吃等死,持续性踌躇满志系列-------------第12天 1.字符串的概述和特点 java.lang.String类代表字符串 API当中说,Java程序中所有的字符串字面值(如“abc& ...
- elementui+vue修改elementUi默认样式不生效
重写,覆盖都不行, ! important 也不行. 原因是 在style标签加了 scoped 的原因.
- vue-cli 3.0
安装 vue-cli 3.0 时报错 vue-cli3安装遇到的问题,卸载不掉旧版本,导致更新不了 vue-cli 2.9.6 版本卸载不了 作者:Runner_leaf链接:https://www. ...
- Flask开发微电影网站(七)
1.后台管理之电影管理 1.1 定义电影表单 在app的admin目录的forms.py文件中,定义电影表单 # 电影表单 class MovieForm(FlaskForm): title = St ...
- npm脚本传参问题
npm脚本传参问题(比如设置env参数) windows环境下: "build": "set NODE_ENV=dev&& gulp", &qu ...
- jade模板 注意事项
1. jade模板 语法 doctype html html head body header div 2. 添加内容:直接在标签后边加空格 直接写内容 如下: div 我要写的内容 3. ...
- mysql case when * else end
分条件计算总数 SELECT -- SUM( END) as am, -- SUM( END) as om , -- SUM( END) as aom , -- SUM( then AmoutPric ...