• 最近点对问题


    问题:设S是平面上n个点的集合,考虑在S种找到一个点对p和q,使其距离最短。求出其最短距离。

    暴力检查每个点对并记录距离后可以选出最短距离,但时间复杂度是O(n2)。

    这里可以运用一种分治的算法,使得时间复杂度降为O(nlogn)。

    算法基本思路:

    1.将所有点排序,优先考虑x,若x相等,则考虑y;

    2.找到中间位置,将集合一分为二,在左边范围内求出最短距离L,在右边范围内求出最短距离R(集合一直划分至三个点后,直接暴力求解);

    3.现在考虑左边的点和右边的点组合能否产生更短的距离。因为现在知道L和R,求出两者中的较小值M,在中间位置各取左边M距离和右边M距离的空间,把其中的左边的点与右边的点暴力求距离值,然后将较小值与M比较,取更小的值即为结果(取2M距离是因为在这个距离外的点与对面的点的距离不可能小于M)。

                

    (图片参考自《ALGORITHMS DESIGN TECHNIQUES AND ANALYSIS》)

    import java.util.Arrays;
    
    class Point implements Comparable {
            
        double x;
        double y;
    
        public int compareTo(Object n){
            Point a = (Point)n;
            if(this.x != a.x){
                return (int)(this.x - a.x);
            }
            return (int)(this.y - a.y);
        }
    
        public String toString(){
            return "(" + x + ", " + y + ")";
        }
    }
    
    public class ClosestPair{
    
        public static double getClosestDistance(Point[] p){
            Arrays.sort(p);
    
            System.out.println(Arrays.toString(p));        //just for test
            
            return cp(p, 0, p.length-1);
        }
    
        private static double computeDistance(Point a, Point b){
            //compute the distance between two points
            return Math.sqrt(Math.pow((a.x-b.x), 2) + Math.pow((a.y-b.y), 2));
        }
    
        private static double cp(Point[] p, int low, int high){
            if(high - low + 1 <= 3){
                //less than 3, directly compute
                double min = computeDistance(p[low], p[high]);
                for(int i = low; i < high; i ++){
                    for(int j = i+1; j <= high; j ++){
                        double temp = computeDistance(p[i], p[j]);
                        min = temp<min? temp:min;
                    }
                }
                return min;
            }
            int mid = (low + high) / 2;
            double x0 = p[mid].x;
            //Divide
            double m = cp(p, low, mid);
            double n = cp(p, mid+1, high);
            //Conguer
            double min = m>n?n:m;
            int k = 0;
            //select the point that the distance between is and p[mid] may be less than min
            Point[] t = new Point[high-low+1];
            for(int i = low; i <= high; i ++){
                if(Math.abs(p[i].x - x0) <= min){
                    t[k++] = p[i];
                }
            }
            double tmin = min * 2;
            for(int i = 0; i < k-1; i ++){
                for(int j = i+1; j < k; j ++){
                    double temp = computeDistance(t[i], t[j]);
                    tmin = temp<tmin? temp:tmin;
                }
            }
            min = tmin<min? tmin:min;
            return min;
        }
    
        public static void main(String[] args){
            Point[] p = new Point[5];
            for(int i = 0; i < p.length; i ++){
                p[i] = new Point();
                p[i].x = (int)(Math.random() * 100);
                p[i].y = (int)(Math.random() * 100);
            }
            System.out.println(getClosestDistance(p));
        }
    }
    Java
  • 相关阅读:
    c#web中定义全局变量,传递变量
    关于Dropdownlist 与 autopostBack 问题多级联动 例 省/市/区
    发布附件应用小研究
    dell更换同型号的主板注意
    dotnet文本编辑器控件的应用
    小结解决双网卡网关问题(route add p) 关于静态路由
    读取数据表中符合条件的记录和数目
    密码最短长度为 7,其中必须包含以下非字母数字字符: 1(转)
    Hibernate 中的核心接口与类
    什么是整洁的代码(Clean Code)?
  • 原文地址:https://www.cnblogs.com/7hat/p/3420151.html
Copyright © 2020-2023  润新知