zoukankan      html  css  js  c++  java
  • 最近点对问题

    问题:设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
  • 相关阅读:
    poj 3122 Pie (二分)
    poj 1905 Expanding Rods(二分)
    poj 3258 River Hopscotch (二分)
    poj 3273 Monthly Expense(二分穷举)
    最小最大堆
    最小—最大堆
    zend studio 9 字体,颜色,快捷键等相关设置
    javascript onbeforeunload
    php DOMDocument 不能解析引用外部DTD的XML
    phpdoc 注释关键字含义
  • 原文地址:https://www.cnblogs.com/7hat/p/3420151.html
Copyright © 2011-2022 走看看