📜  优化点的位置以最小化总距离

📅  最后修改于: 2021-05-04 13:11:52             🧑  作者: Mango

给定一组点as和一条线,其ax + by + c =0。我们需要在给定线上找到一个点,距给定点集的距离之和最小。

例子:

In above figure optimum location of point of x - y - 3 = 0 line 
is (2, -1), whose total distance with other points is 20.77, 
which is minimum obtainable total distance.

如果我们在给定线上以无限距离取一个点,那么总距离成本将是无限的,现在当我们将此点朝着给定点移动时,总距离成本开始下降,一段时间后,它又开始增加,直到达到无限远。线的另一无穷尽,因此距离成本曲线看起来像U形曲线,我们必须找到该U形曲线的底值。

由于U曲线不是单调递增或递减的,因此我们不能使用二进制搜索来找到最底点,这里我们将使用三元搜索来找到最底点,三元搜索在每次迭代时都跳过搜索空间的三分之一,您可以阅读有关三元搜索的更多信息,请点击此处。

因此,解决方案如下进行,首先从低和高开始,分别初始化为一些最小和最大值,然后开始迭代,在每次迭代中,我们计算两个中点Mid1和Mid2,分别代表搜索的1/3和2 / 3rd位置。在空间上,我们计算中点1和中点2的所有点的总距离,并通过比较这些距离成本来更新低点或高点,此迭代持续进行,直到低点和高点变得近似相等为止。

C++
//  C/C++ program to find optimum location and total cost
#include 
using namespace std;
#define sq(x) ((x) * (x))
#define EPS 1e-6
#define N 5
 
//  structure defining a point
struct point {
    int x, y;
    point() {}
    point(int x, int y)
        : x(x)
        , y(y)
    {
    }
};
 
//  structure defining a line of ax + by + c = 0 form
struct line {
    int a, b, c;
    line(int a, int b, int c)
        : a(a)
        , b(b)
        , c(c)
    {
    }
};
 
//  method to get distance of point (x, y) from point p
double dist(double x, double y, point p)
{
    return sqrt(sq(x - p.x) + sq(y - p.y));
}
 
/*  Utility method to compute total distance all points
    when choose point on given line has x-cordinate
    value as X   */
double compute(point p[], int n, line l, double X)
{
    double res = 0;
 
    //  calculating Y of choosen point by line equation
    double Y = -1 * (l.c + l.a * X) / l.b;
    for (int i = 0; i < n; i++)
        res += dist(X, Y, p[i]);
 
    return res;
}
 
//  Utility method to find minimum total distance
double findOptimumCostUtil(point p[], int n, line l)
{
    double low = -1e6;
    double high = 1e6;
 
    // loop untill difference between low and high
    // become less than EPS
    while ((high - low) > EPS) {
        // mid1 and mid2 are representative x co-ordiantes
        // of search space
        double mid1 = low + (high - low) / 3;
        double mid2 = high - (high - low) / 3;
 
        //
        double dist1 = compute(p, n, l, mid1);
        double dist2 = compute(p, n, l, mid2);
 
        // if mid2 point gives more total distance,
        // skip third part
        if (dist1 < dist2)
            high = mid2;
 
        // if mid1 point gives more total distance,
        // skip first part
        else
            low = mid1;
    }
 
    // compute optimum distance cost by sending average
    // of low and high as X
    return compute(p, n, l, (low + high) / 2);
}
 
//  method to find optimum cost
double findOptimumCost(int points[N][2], line l)
{
    point p[N];
 
    //  converting 2D array input to point array
    for (int i = 0; i < N; i++)
        p[i] = point(points[i][0], points[i][1]);
 
    return findOptimumCostUtil(p, N, l);
}
 
//  Driver code to test above method
int main()
{
    line l(1, -1, -3);
    int points[N][2] = {
        { -3, -2 }, { -1, 0 }, { -1, 2 }, { 1, 2 }, { 3, 4 }
    };
    cout << findOptimumCost(points, l) << endl;
    return 0;
}


Java
// A Java program to find optimum location
// and total cost
class GFG {
    static double sq(double x) { return ((x) * (x)); }
    static int EPS = (int)(1e-6) + 1;
    static int N = 5;
 
    // structure defining a point
    static class point {
        int x, y;
        point() {}
 
        public point(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
    };
 
    // structure defining a line of ax + by + c = 0 form
    static class line {
        int a, b, c;
 
        public line(int a, int b, int c)
        {
            this.a = a;
            this.b = b;
            this.c = c;
        }
    };
 
    // method to get distance of point (x, y) from point p
    static double dist(double x, double y, point p)
    {
        return Math.sqrt(sq(x - p.x) + sq(y - p.y));
    }
 
    /* Utility method to compute total distance all points
        when choose point on given line has x-cordinate
        value as X */
    static double compute(point p[], int n, line l,
                          double X)
    {
        double res = 0;
 
        // calculating Y of choosen point by line equation
        double Y = -1 * (l.c + l.a * X) / l.b;
        for (int i = 0; i < n; i++)
            res += dist(X, Y, p[i]);
 
        return res;
    }
 
    // Utility method to find minimum total distance
    static double findOptimumCostUtil(point p[], int n,
                                      line l)
    {
        double low = -1e6;
        double high = 1e6;
 
        // loop untill difference between low and high
        // become less than EPS
        while ((high - low) > EPS) {
            // mid1 and mid2 are representative x
            // co-ordiantes of search space
            double mid1 = low + (high - low) / 3;
            double mid2 = high - (high - low) / 3;
 
            double dist1 = compute(p, n, l, mid1);
            double dist2 = compute(p, n, l, mid2);
 
            // if mid2 point gives more total distance,
            // skip third part
            if (dist1 < dist2)
                high = mid2;
 
            // if mid1 point gives more total distance,
            // skip first part
            else
                low = mid1;
        }
 
        // compute optimum distance cost by sending average
        // of low and high as X
        return compute(p, n, l, (low + high) / 2);
    }
 
    // method to find optimum cost
    static double findOptimumCost(int points[][], line l)
    {
        point[] p = new point[N];
 
        // converting 2D array input to point array
        for (int i = 0; i < N; i++)
            p[i] = new point(points[i][0], points[i][1]);
 
        return findOptimumCostUtil(p, N, l);
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        line l = new line(1, -1, -3);
        int points[][] = { { -3, -2 },
                           { -1, 0 },
                           { -1, 2 },
                           { 1, 2 },
                           { 3, 4 } };
        System.out.println(findOptimumCost(points, l));
    }
}
 
// This code is contributed by Rajput-Ji


Python3
# A Python3 program to find optimum location
# and total cost
import math
 
class Optimum_distance:
     
    # Class defining a point
    class Point:
         
        def __init__(self, x, y):
             
            self.x = x
            self.y = y 
         
    # Class defining a line of ax + by + c = 0 form
    class Line:
         
        def __init__(self, a, b, c):
             
            self.a = a
            self.b = b
            self.c = c
         
    # Method to get distance of point
    # (x, y) from point p
    def dist(self, x, y, p):
         
        return math.sqrt((x - p.x) ** 2 +
                         (y - p.y) ** 2)
       
    # Utility method to compute total distance
    # all points when choose point on given
    # line has x-cordinate value as X
    def compute(self, p, n, l, x):
         
        res = 0
         
        y = -1 * (l.a*x + l.c) / l.b
         
        # Calculating Y of choosen point
        # by line equation
        for i in range(n):
            res += self.dist(x, y, p[i])
             
        return res
     
    # Utility method to find minimum total distance
    def find_Optimum_cost_untill(self, p, n, l):
         
        low = -1e6
        high = 1e6
         
        eps = 1e-6 + 1
         
         
        # Loop untill difference between low
        # and high become less than EPS
        while((high - low) > eps):
           
              # mid1 and mid2 are representative x
            # co-ordiantes of search space
            mid1 = low + (high - low) / 3
            mid2 = high - (high - low) / 3
             
            dist1 = self.compute(p, n, l, mid1)
            dist2 = self.compute(p, n, l, mid2)
             
            # If mid2 point gives more total
            # distance, skip third part
            if (dist1 < dist2):
                high = mid2
                 
            # If mid1 point gives more total
            # distance, skip first part
            else:
                low = mid1
                 
        # Compute optimum distance cost by
        # sending average of low and high as X
        return self.compute(p, n, l, (low + high) / 2)
     
    # Method to find optimum cost
    def find_Optimum_cost(self, p, l):
         
        n = len(p)
        p_arr = [None] * n
         
        # Converting 2D array input to point array
        for i in range(n):
            p_obj = self.Point(p[i][0], p[i][1])
            p_arr[i] =  p_obj
             
        return self.find_Optimum_cost_untill(p_arr, n, l)
       
 # Driver Code
if __name__ == "__main__":
     
    obj = Optimum_distance()
    l = obj.Line(1, -1, -3)
     
    p = [ [ -3, -2 ], [ -1, 0 ],
          [ -1, 2 ], [ 1, 2 ],
          [ 3, 4 ] ]
     
    print(obj.find_Optimum_cost(p, l))
     
# This code is contributed by Sulu_mufi


C#
// C# program to find optimum location
// and total cost
using System;
 
class GFG {
    static double sq(double x) { return ((x) * (x)); }
 
    static int EPS = (int)(1e-6) + 1;
    static int N = 5;
 
    // structure defining a point
    public class point {
        public int x, y;
        public point() {}
 
        public point(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
    };
 
    // structure defining a line
    // of ax + by + c = 0 form
    public class line {
        public int a, b, c;
 
        public line(int a, int b, int c)
        {
            this.a = a;
            this.b = b;
            this.c = c;
        }
    };
 
    // method to get distance of
    // point (x, y) from point p
    static double dist(double x, double y, point p)
    {
        return Math.Sqrt(sq(x - p.x) + sq(y - p.y));
    }
 
    /* Utility method to compute total distance
    of all points when choose point on
    given line has x-cordinate value as X */
    static double compute(point[] p, int n, line l,
                          double X)
    {
        double res = 0;
 
        // calculating Y of choosen point
        // by line equation
        double Y = -1 * (l.c + l.a * X) / l.b;
        for (int i = 0; i < n; i++)
            res += dist(X, Y, p[i]);
 
        return res;
    }
 
    // Utility method to find minimum total distance
    static double findOptimumCostUtil(point[] p, int n,
                                      line l)
    {
        double low = -1e6;
        double high = 1e6;
 
        // loop untill difference between
        // low and high become less than EPS
        while ((high - low) > EPS) {
            // mid1 and mid2 are representative
            // x co-ordiantes of search space
            double mid1 = low + (high - low) / 3;
            double mid2 = high - (high - low) / 3;
 
            double dist1 = compute(p, n, l, mid1);
            double dist2 = compute(p, n, l, mid2);
 
            // if mid2 point gives more total distance,
            // skip third part
            if (dist1 < dist2)
                high = mid2;
 
            // if mid1 point gives more total distance,
            // skip first part
            else
                low = mid1;
        }
 
        // compute optimum distance cost by
        // sending average of low and high as X
        return compute(p, n, l, (low + high) / 2);
    }
 
    // method to find optimum cost
    static double findOptimumCost(int[, ] points, line l)
    {
        point[] p = new point[N];
 
        // converting 2D array input to point array
        for (int i = 0; i < N; i++)
            p[i] = new point(points[i, 0], points[i, 1]);
 
        return findOptimumCostUtil(p, N, l);
    }
 
    // Driver Code
    public static void Main(String[] args)
    {
        line l = new line(1, -1, -3);
        int[, ] points = { { -3, -2 },
                           { -1, 0 },
                           { -1, 2 },
                           { 1, 2 },
                           { 3, 4 } };
        Console.WriteLine(findOptimumCost(points, l));
    }
}
 
// This code is contributed by 29AjayKumar


输出
20.7652