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
  • 相关阅读:
    【应用安全】mssql db_owner权限拿shell
    【应用安全——XSS】input-hidden
    留言板
    Git配置多个SSH-Key
    13.InternalThreadLocalMap
    10.ChannelOutboundBuffer
    9.ChannelHandlerContext
    8.Future&Promise
    7.给大动脉来一刀-NioEventLoop 源码分析
    6.给大动脉来一刀
  • 原文地址:https://www.cnblogs.com/7hat/p/3420151.html
Copyright © 2011-2022 走看看