Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 701|回复: 0

用蛮力法和分治法求解最近对问题 java实例

[复制链接]

该用户从未签到

发表于 2011-9-18 16:30:01 | 显示全部楼层 |阅读模式
问题:
设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。

蛮力算法描述:
int ClosestPoints(int n, int x[ ], int y[ ]){
   minDist=Double.POSITIVE_INFINITY;;
   for (i=1; i< n; i++)
      for (j=i+1; j<=n; j++)
     {
         d=(x-x[j])* (x-x[j])+(y-y[j])* (y-y[j]);
         if (d< minDist) {
             minDist=d;
             index1=i;
             index2=j;
        }
      }
     return  minDist;
}
程序:

import java.util.*;
public class ClosestPair1{
public static void main(String[] args)
{
  /**
   *输入需要比较的点的对数存在变量n中
   */
  Scanner in=new Scanner(System.in);
  System.out.println("How many pairs of points to compare?(有多少对点需要比较?)");
  int n=in.nextInt();
  
  int[] x=new int[n];
  int[] y=new int[n];
  /**
   *输入这些点的横坐标和纵坐标分别存储在x[n]和y[n]
   */
  System.out.println(&quotlease enter these points,X-coordinate(请输入这些点,横坐标):");
  for(int i=0;i< n;i++)
  {
   x=in.nextInt();
  }
  
  System.out.println("Please enter these points,Y-coordinate(请输入这些点,纵坐标):");
  for(int i=0;i< n;i++)
  {
   y=in.nextInt();
  }
  
  double minDist=Double.POSITIVE_INFINITY;
  double d;
  int indexI=0;
  int indexJ=0;
        /**
         *求解最近对距离存于minDist中
         */
        double startTime=System.currentTimeMillis();//startTime
  for(int i=0;i< n-1;i++)
  {
   for(int j=i+1;j< n;j++)
    {
     d=Math.sqrt((x-x[j])*(x-x[j])+(y-y[j])*(y-y[j]));
     if(d< minDist)
     {
      minDist=d;
      indexI=i;
      indexJ=j;
     }      
    }
  }
  double endTime=System.currentTimeMillis();//endTime
  /**
   *打印输出最后求出的结果,最近的是哪两个点,以及最近距离和程序用的时间
   */
  System.out.println("The closest pair is"+x[indexI]+","+y[indexI]+") and ("+x[indexJ]+","+y[indexJ]+")");
  System.out.println("The closest distance is "+minDist);
  System.out.println("Basic Statements take(基本语句用时) "+(endTime-startTime)+" milliseconds!");
}
}
运行:


分治算法 描述:
   可以划一条垂线,把点集分成两半:PL和PR。于是最近点对或者在PL中,或者在PR中,或者PL,PR各有一点。
把三种距离情况定义为dL, dR, dC.

    其中dL, dR可以递归求解,于是问题就变为计算dC。

设s=min(dL, dR). 通过观察能得出结论:如果dC<s,则只需计算dC。如果dC满足这样的条件,则决定dC的两点必然在分割线的s距离之内,称之为带(strip)
否则不可能满足dC<s, 于是缩小了需要考虑的点的范围。



程序:
import java.util.*;
public class ClosestPair2
{
public static void main(String[] args)
{
  /**
   *输入需要比较的点的对数存在变量n中
   */
  Scanner in=new Scanner(System.in);
  System.out.println("How many pairs of points to compare?(有多少对点需要比较?)");
  int n=in.nextInt();
  /**
   *输入这些点的横坐标和纵坐标,存储在点数组S[n]中
   */
  System.out.println("Please enter these points,X-coordinate and Y-coordinate.(请输入这些点,x坐标和y坐标):");
  Point[] S=new Point[n];
  
  double startTime=System.currentTimeMillis();//starttime
  
  for(int i=0;i< n;i++)
  {
   int x=in.nextInt();
   int y=in.nextInt();
   S=new Point(x,y);
   System.out.println("("+S.getX()+","+S.getY()+")");
  }
  
  /**
   *求出这点的x坐标的中位数mid
   */
  int minX=(int)Double.POSITIVE_INFINITY;
  int maxX=(int)Double.NEGATIVE_INFINITY;
  for(int i=0;i< n;i++)
  {
   if(S.getX()< minX)
    minX=S.getX();
   if(S.getX()>maxX)
    maxX=S.getX();
  }
  
  int mid=(minX+maxX)/2;
  /**
   *以mid为界把S中的点分为两组分别存放在范型数组列表point1和point2中
   */
  ArrayList point1=new ArrayList();
  ArrayList point2=new ArrayList();
  for(int i=0;i< n;i++)
  {
   if(S.getX()<=mid)
    point1.add(S);
   else
    point2.add(S);
  }
  
  /**
   *将范型数组列表转换为数组类型S1和S2
   */
     Point[] S1=new Point[point1.size()];
     Point[] S2=new Point[point2.size()];
     point1.toArray(S1);
     point2.toArray(S2);
     
  /**
   *将S1和S2中的点按x 坐标升序排列
   */
  sortX(S1);
  sortX(S2);
  
  /**
   *打印输出排序后S1和S2的点
   */
  System.out.print("The points in S1 are:");
  for(int i=0;i< S1.length;i++)
   System.out.print("("+S1.getX()+","+S1.getY()+") ");
  System.out.println();
  System.out.print("The points in S2 are:");
  for(int i=0;i< S2.length;i++)
   System.out.print("("+S2.getX()+","+S2.getY()+") ");
  System.out.println();
  
  /**
   *求S1中点的最近对及其距离并打印输出结果
   */
  double minDist1=Double.POSITIVE_INFINITY;
  int indexI1=0;
  int indexJ1=0;
  for(int i=0;i< S1.length-1;i++)
   {
    for(int j=i+1;j< S1.length;j++)
     {
      double d=Math.sqrt(Math.pow((S1.getX()-S1[j].getX()),2)+Math.pow((S1.getY()-S1[j].getY()),2));
      if(d< minDist1)
       {
        minDist1=d;
        indexI1=i;
        indexJ1=j;
       }      
     }
   }
   
  System.out.println("The closest pair in S1 is: "+"("+S1[indexI1].getX()+","+S1[indexI1].getY()+")"+
   "and("+S1[indexJ1].getX()+","+S1[indexJ1].getY()+")"+",and the distance is "+minDist1);
  /**
   *求S2中点的最近对及其距离并打印输出结果
   */
  double minDist2=Double.POSITIVE_INFINITY;
  int indexI2=0;
  int indexJ2=0;
  for(int i=0;i< S2.length-1;i++)
   {
    for(int j=i+1;j< S2.length;j++)
     {
      double d=Math.sqrt(Math.pow((S2.getX()-S2[j].getX()),2)+Math.pow((S2.getY()-S2[j].getY()),2));
      if(d< minDist2)
       {
        minDist2=d;
        indexI2=i;
        indexJ2=j;
       }      
     }
   }
  System.out.println("The closest pair in S2 is: "+"("+S2[indexI2].getX()+","+S2[indexI2].getY()+")"+
   "and("+S2[indexJ2].getX()+","+S2[indexJ2].getY()+")"+",and the distance is "+minDist2);
  
  double d1=Math.min(minDist1,minDist2);
  /**
   *在S1,S2中收集距离中线两侧小于dl的点,分别存在P1[]和P2[]中
   */
  ArrayList< Point> pp1=new ArrayList< Point>();
  ArrayList< Point> pp2=new ArrayList< Point>();
  for(int i=0;i< S1.length;i++)
  {
   if((mid-S1.getX())< d1)
    pp1.add(S1);
  }
  for(int i=0;i< S2.length;i++)
  {
   if((S2.getX()-mid)< d1)
    pp2.add(S2);
  }
  
  Point[] P1=new Point[pp1.size()];
     Point[] P2=new Point[pp2.size()];
     pp1.toArray(P1);
     pp2.toArray(P2);
     
  /**
   *将P1和P2中的点按Y坐标升序排列
   */
  sortY(P1);
  sortY(P2);
  /**
   *求解P1和P2两者之间可能的最近对距离
   */
  double d2=Double.POSITIVE_INFINITY;
  for(int i=0;i< P1.length;i++)
  {
   for(int j=0;j< P2.length;j++)
   {
    if(Math.abs(P1.getY()-P2[j].getY())< d1)
    {
     double temp=Math.sqrt(Math.pow((P1.getX()-P2[j].getX()),2)+Math.pow((P1.getX()-P2[j].getX()),2));
     if(temp< d2)
      d2=temp;   
    }   
   }
  }
  
  double endTime=System.currentTimeMillis();//endtime
  /**
   *打印输出最后求出的结果,最近的是哪两个点,以及最近距离和程序用的时间
   */
  System.out.print("The points in P1 are:");
  for(int i=0;i< P1.length;i++)
   System.out.print("("+P1.getX()+","+P1.getY()+") ");
  System.out.println();
  System.out.print("The points in P2 are:");
  for(int i=0;i< P2.length;i++)
   System.out.print("("+P2.getX()+","+P2.getY()+") ");
  System.out.println();
  System.out.println("d2="+d2);
  double minDist=Math.min(d1,d2);
  System.out.println("The closest distance is "+minDist);
  
  System.out.println("Basic Statements take(基本语句用时) "+(endTime-startTime)+" milliseconds!");  
}
/**
  *设计按点Point的x坐标升序排列的函数sortX
  */
public static void sortX(Point[] p)
{
  for(int i=0;i< p.length-1;i++)
  {
   for(int j=0;j< p.length-1-i;j++)
   {
    if(p[j].getX()>p[j+1].getX())
    {
     int t=p[j].getX();
     p[j].setX(p[j+1].getX());
     p[j+1].setX(t);
     
     int n=p[j].getY();
     p[j].setY(p[j+1].getY());
     p[j+1].setY(n);
    }
   }
  }
}
/**
  *设计按点Point的y坐标升序排列的函数sortY
  */
public static void sortY(Point[] p)
{
  for(int i=0;i< p.length-1;i++)
  {
   for(int j=0;j< p.length-1-i;j++)
   {
    if(p[j].getY()>p[j+1].getY())
    {
     int t=p[j].getY();
     p[j].setY(p[j+1].getY());
     p[j+1].setY(t);
     
     int n=p[j].getX();
     p[j].setX(p[j+1].getX());
     p[j+1].setX(n);
    }
   }
  }
}
}
/**
* 建立自己的类Point
*/
class Point implements Cloneable
{
public Point()
{
  x=0;
  y=0;
}

public Point(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;
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2024-5-27 06:20 , Processed in 0.361926 second(s), 39 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表