一、问题描述

给定平面上的n个点,找其中的一对点,使得在n个点组成的所有点对中该点对间的距离最小。

二、解题思路及所选算法策略的可行性分析

思路:利用分治法来解决问题。递归子结构求最接近点对总体可分为几个步骤:

1、当问题规模小于20,直接求解最小点对

2、将n个点组成的集合S分成2个子集S1和S2

3、递归求出两个子集中的最接近点对并比较出最小点对,记录距离dmin

4、以X坐标为基准找到所有点中线,在中线附近找出相距可能小于dmin的点对点,记录于S3和S4

5、求S3和S4每点对距离,和dmin进行比较,求解最接近点对

策略可行性分析:

设直线l上有2m个点,以m为中点将l分割成两条线段dl,dr,然后求出dl和dr这两点条线段中的最小点距d1,d2,此时d=min{d1,d2},再通过计算出dl线段的中最大点与dr线段中的最小点之间的距离D,最小距离则为min{d,D}.

二维情况与此相似,最大的区别只是对于中线位置的点,二维情况只是针对中线旁好多可能点,再在Y轴方向上进行点的筛选,以减少平方计算次数。

三、伪代码描述及复杂度分析

Public static double closestPoint(S)

{

1、首先,递归结束条件,当数组长度在一定范围内时直接求出最近点,蛮力求解

2、求所有点在X坐标中的中位数midX

3、以midX为界将所有点分成两组分别存放在两个表中

4、将两张表转化为数组类型,并分别按X坐标升序排列

5、求S1中的最近距离的两个点

6、求S2中的最近距离的两个点

7、求两最近距离的最小值

8、在S1、S2中收集距离中线小于d1的点,分别存放于两个表中

9、分别将表T3、T4转换为数组类型的S3、S4,并将其分别按Y坐标升序排列

10、求解S3、S4两者之间可能的更近(相比于d1)距离 , 以及构成该距离的点

}

复杂度分析:

设算法耗时T(n)。 算法第1步、第2步、第3步和第8步用了O(n)时间。第7步和第10步用了常数时间。第4步和第9步用了O(nlogn)时间。第5步和第6步分别用了T(n/2)时间。不过第4步和第9步是数组的排序预处理时间,所以不算在算法中。所以经由预处理的算法所需计算时间满足递归方程:

T(n)={   O(1)          n<4

2T(n/2)+O(n)   n>=4

由此,T(n)=O(nlogn)。

代码实现

dcPoint.java

package 分治法;

public class dcPoint implements Cloneable, Comparable{

public dcPoint() {

x = 0;

y = 0;

}

public dcPoint(int x, int y) {

this.x = x;

this.y = y;

}

public void setX(int x) {

this.x = x;

}

public void setY(int y) {

this.y = y;

}

public int getX() {

return x;

}

public int getY() {

return y;

}

private int x;

private int y;

@Override

public int compareTo(dcPoint o) {

if(x == o.getX() && y == o.getY())

return 0;

else

return 1;

}

}

NPointPair.java

package 分治法;

import java.util.ArrayList;

import java.util.Random;

import java.util.Set;

import java.util.TreeSet;

public class NPointPair {

/**

* 最近点问题

* @param S

*/

public static dcPoint[] closestPoint(dcPoint [] S){

dcPoint[] result = new dcPoint[2];

/**

* 0.首先,解决该问题的边界,当数组长度在一定范围内时直接求出最近点,蛮力求解

*/

double dmin = Double.POSITIVE_INFINITY;

double tmpmin = 0;

if(S.length <= 20){

for(int i = 0; i < S.length; i ++){

for(int j = i + 1; j < S.length; j ++){

tmpmin = Math.sqrt(Math.pow(S[i].getX() - S[j].getX(), 2)) + Math.pow(S[i].getY() - S[j].getY(), 2);

if(tmpmin < dmin){

dmin = tmpmin;

result[0] = S[i];

result[1] = S[j];

}

}

}

return result;

}

/**

*1.求所有点在X坐标的中位数

*/

int minX = (int) Double.POSITIVE_INFINITY;//保证假设的初始最小值足够大

int maxX = (int) Double.NEGATIVE_INFINITY;//保证假设的初始最大值足够小

for(int i = 0; i < S.length; i++){

if(S[i].getX() < minX)

minX = S[i].getX();

if(S[i].getX() > maxX)

maxX = S[i].getX();

}

int midX = (minX + maxX)/2;

/**

* 2.以midX为界将所有点分成两组分别存放在两个表中

*/

ArrayList T1 = new ArrayList();

ArrayList T2 = new ArrayList();

for(int i = 0; i < S.length; i++){

if(S[i].getX() <= midX)//是否要=号?

T1.add(S[i]);

if(S[i].getX() > midX)

T2.add(S[i]);

}

/**

* 3.将两张表转化为数组类型,并分别按X坐标升序排列

*/

dcPoint [] S1 = new dcPoint[T1.size()];

dcPoint [] S2 = new dcPoint[T2.size()];

T1.toArray(S1);

T2.toArray(S2);

mergeSort(S1, "x");//按X坐标升序排列

mergeSort(S2, "x");//按X坐标升序排列

/**

* 4.求S1中的最近距离的两个点

*/

dcPoint[] result1 = new dcPoint[2];

result1 = closestPoint(S1);

/**

* 5.求S2中的最近距离的两个点

*/

dcPoint[] result2 = new dcPoint[2];

result2 = closestPoint(S2);

/**

* 6.求两最近距离的最小值

*/

double d1 = Math.sqrt(Math.min(Math.pow(result1[0].getX() - result1[1].getX(), 2) + Math.pow(result1[0].getY() - result1[1].getY(), 2),

Math.pow(result2[0].getX() - result2[1].getX(), 2) + Math.pow(result2[0].getY() - result2[1].getY(), 2)));

if(Math.pow(result1[0].getX() - result1[1].getX(), 2) + Math.pow(result1[0].getY() - result1[1].getY(), 2) <

Math.pow(result2[0].getX() - result2[1].getX(), 2) + Math.pow(result2[0].getY() - result2[1].getY(), 2))

result = result1;

else

result = result2;

/**

* 7.在S1、S2中收集距离中线小于d1的点,分别存放于两个表中

*/

ArrayList T3 = new ArrayList();

ArrayList T4 = new ArrayList();

for(int i = 0; i < S1.length; i++){

if(midX - S1[i].getX() < d1)

T3.add(S1[i]);

}

for(int i = 0; i < S2.length; i++){

if(S2[i].getX() - midX < d1){

T4.add(S2[i]);

}

}

/**

* 8.分别将表T3、T4转换为数组类型的S3、S4,并将其分别按Y坐标升序排列

*/

dcPoint [] S3 = new dcPoint [T3.size()];

dcPoint [] S4 = new dcPoint [T4.size()];

T3.toArray(S3);

T4.toArray(S4);

mergeSort(S3, "y");

mergeSort(S4, "y");

/**

* 求解S3、S4两者之间可能的更近(相比于d1)距离 , 以及构成该距离的点

*/

double d = Double.POSITIVE_INFINITY;

for(int i = 0; i < S3.length; i ++){

for(int j = 0; j < S4.length; j ++){

if(Math.abs(S3[i].getY() - S4[j].getY()) < d1){

double tmp = Math.sqrt(Math.pow(S3[i].getX() - S4[j].getX(), 2) + Math.pow(S3[i].getY() - S4[j].getY(), 2));

if(tmp < d){

d = tmp;

result[0] = S3[i];

result[1] = S4[j];

}

}

}

}

return result;

}

//归并排序

private static void mergeSort(dcPoint[] a, String property){

dcPoint[] tempArray = new dcPoint[a.length];

mergeSort(a, tempArray, 0, a.length - 1, property);

}

private static void mergeSort(dcPoint[] a, dcPoint [] tempArray, int left, int right, String property){

if(left < right){

int center = (left + right) >> 1;

//分治

mergeSort(a, tempArray, left, center, property);

mergeSort(a, tempArray, center + 1, right, property);

//合并

merge(a, tempArray, left, center + 1, right, property);

}

}

private static void merge(dcPoint [] a, dcPoint [] tempArray, int leftPos, int rightPos, int rightEnd, String property){

int leftEnd = rightPos - 1;

int numOfElements = rightEnd - leftPos + 1;

int tmpPos = leftPos;//游标变量, 另两个游标变量分别是leftPos 和 rightPos

while(leftPos <= leftEnd && rightPos <= rightEnd){

if(property.equals("x")){

if(a[leftPos].getX() <= a[rightPos].getX())

tempArray[tmpPos++] = a[leftPos++];

else

tempArray[tmpPos++] = a[rightPos++];

}else if(property.equals("y")){

if(a[leftPos].getY() <= a[rightPos].getY())

tempArray[tmpPos++] = a[leftPos++];

else

tempArray[tmpPos++] = a[rightPos++];

}else

throw new RuntimeException();

}

while(leftPos <= leftEnd)

tempArray[tmpPos++] = a[leftPos++];

while(rightPos <= rightEnd)

tempArray[tmpPos++] = a[rightPos++];

//将排好序的段落拷贝到原数组中

System.arraycopy(tempArray, rightEnd-numOfElements+1, a, rightEnd-numOfElements+1, numOfElements);

}

public static void main(String[] args) {

Set testData = new TreeSet();

Random random = new Random();

int x = 0;

int y = 0;

for(int i = 0;i < 50;i++){

x = random.nextInt(500);

y = random.nextInt(500);

System.out.println("x:" + x + " y:" + y);

testData.add(new dcPoint(x, y));

}

dcPoint [] S = new dcPoint[testData.size()];

S = (dcPoint[]) testData.toArray(S);

for(int i = 0; i < S.length; i ++){

System.out.println("(" + S[i].getX() + ", " + S[i].getY() + ")");

}

System.out.println(testData.size());

dcPoint [] result = new dcPoint [2];

result = closestPoint(S);

System.out.println("最近的两点分别是(" + result[0].getX() + ", " + result[0].getY()

+ ") 和 (" + result[1].getX() + ", " + result[1].getY() + "), 最近距离为:"

+ Math.sqrt(Math.pow(result[0].getX() - result[1].getX(), 2) + Math.pow(result[0].getY() - result[1].getY(), 2)));

}

}

java最接近对点及距离_最接近点对问题_分治法相关推荐

  1. c++分治法求最大最小值实现_程序员:算法导论,分治法、归并排序,伪代码和Java实现...

    分治法 我们首先先介绍分治法.分治法的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后在合并这些子问题的解来解决原问题的解. 还是拿扑克牌举例子,假设桌上有两堆牌面朝 ...

  2. 分治法-最接近点对问题

    背景: 计算机应用中经常采用点.圆等简单的几何对象表示物理实体,常需要了解其邻域中其他几何对象的信息 例如:在空中交通控制中,若将飞机作为空间中的一个点来处理,则具有最大碰撞危险的两架飞机所处的点对, ...

  3. java怎么指定父窗口大小_[Java教程]jQuery如何获取div距离窗口顶部或者父元素顶部的距离...

    [Java教程]jQuery如何获取div距离窗口顶部或者父元素顶部的距离 0 2016-01-03 11:00:19 jQuery如何获取div距离窗口顶部或者父元素顶部的距离: 在实际应用或许会需 ...

  4. oracle 经纬度算距离,根据经纬度诀别用java和Oracle存储过程计算两点距离

    根据经纬度分别用java和Oracle存储过程计算两点距离 create or replace procedure SP_GET_DISTANCE (cx in number,cy in number ...

  5. java计算抛物线的标准方程_抛物线方程公式大全_抛物线的四种标准方程_抛物线公式_抛物线方程及图像_高中数学知识点总结网...

    宜城教育资源网www.ychedu.com抛物线方程公式大全_抛物线的四种标准方程_抛物线公式_抛物线方程及图像_高中数学知识点总结网抛物线方程定义编辑抛物线定义:平面内与一个定点F和一条直线l的距离 ...

  6. java分治法求数列的最大子段和_同事为进大厂天天刷Java面试题,面试却履败!究其原因竟是它在捣鬼。...

    写在前面 疫情过后,招聘与求职受影响到底有多大?我不知道,但我的真实感受是,即使有疫情的影响,最近还是持续有朋友来跟我说他们今年工作的新动向.有人跳槽去了大厂,有人下定决心出来创业,也有人还在观望,等 ...

  7. java 分治法排序_分治法实现1-N的数字按字典序全排列组合 Java语言

    package 分治法; import java.util.Arrays; /* * 将数字 1 - n进行全排列 按字典序从小到大输出 * 如 1 - 3 * 123 132 213 231 312 ...

  8. 计算机系素描教材,美术入门级素描的掌握_计算机软件及应用_IT计算机_专业资料...

    美术入门级素描的掌握_计算机软件及应用_IT计算机_专业资料 (4页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 17:19][热度:160 ...

  9. 计算机编程导论python程序设计答案-学堂在线_计算机科学与Python编程导论_作业课后答案...

    学堂在线_计算机科学与Python编程导论_作业课后答案 答案: 更多相关问题 近代中国完全沦为半殖民地半封建社会的标志是:A.<马关条约>B.<辛丑条约>C.<凡尔赛和 ...

最新文章

  1. mac 下搭建 php + apache + mysql 服务器(cool)
  2. 运维软件PE工具箱下载附制作、安装教程
  3. C#读写xml文件应用
  4. 【cJSon】cJSON学习笔记(一)
  5. 步步为营UML建模系列总结
  6. springboot服务调用超时_Spring Boot 异步请求和异步调用,一文搞定
  7. Python分析年度爆款“网抑云”热评,看看哪些文案触动了你的内心世界?
  8. angular1 搜索服务 ,震灾名称是必填
  9. js获取手机屏幕宽度、高度
  10. 首都师范 博弈论 5 4 2 Shapley值应用案例
  11. java word导出表格_Java实现word导出(表格带图片)
  12. imu可视化和frame_id的查询
  13. 数据分析-用python分析中国五大城市的PM2.5值(ols建立回归模型)
  14. 华为认证云服务架构专家正式发布!
  15. 2021-08-30-全排列-逆序数-排列的奇偶性
  16. 淘宝商品点赞可以增加权重吗?
  17. VirtualBox中Windows 7虚拟机无法全屏显示怎么办?
  18. 【Novel AI】使用绘画AI构建unity游戏资源
  19. matlab中函数imresize的使用介绍
  20. 京东市值增近500亿,刘强东却接二连三卸任,这下的是什么棋?

热门文章

  1. linux实现自己的write函数,Linux 内核源码阅读 - write 系统调用的实现
  2. HTML5链接tcpUDP,UDP/TCP协议 网络调试工具源码(C#)
  3. HTML多选mysql,html多选下拉框 | 学步园
  4. Problem C: 结构体---点坐标结构体
  5. Simple Addition expression【打表+二分】
  6. 分布式数据库中间件使用经验分享
  7. Confluence 6 workbox 通知包含了什么
  8. Failed to start firewalld.service: Unit firewalld.service is masked.
  9. 控制JSP头部引入外部文件编译后在第一行
  10. 固有属性与自定义属性