Open In App

Minimize Sum of Distance in 2D Plane

Last Updated : 26 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given N points in the 2D plane such that each point has a weight Wi. The task is to find a point K such that the sum of the total distance between point K and each point is minimized, such that

  • The distance between point K and point Pi is calculated as Manhattan distance(K, Pi)*Wi. (i.e., Manhattan Distance between point K and Pi multiplied by the weight of point Pi).
  • Manhattan distance is the distance between two points measured along axes at right angles. In a plane with p1 at (x1, y1) and p2 at (x2, y2), it is |x1 – x2| + |y1 – y2|.

Find-Minimum-Weighted-Sum-Of-Distance-In-2D-Plane

Examples:

Input: N = 2, Points = [ [0, 0], [2, 2] ], Weights = [1, 2]
Output: 4
Explanation: Point K chosen here is (2,2). So total sum of Distance is 1*(2+2)+2*(0+0)=4

Input: N = 2, Points = [ [0, 0], [2, 2] ], Weights = [1, 1]
Output: 4
Explanation: Point K chosen here is (1,1). So total sum of Distance is 1*(1+1)+1*(1+1)=4

Naive Approach:

If we solve this problem using the Naive Approach, we will be doing hit and trial to find a suitable point that satisfies the required conditions for K.

Efficient Approach:

Idea:

If we follow the Naive Approach, there can be a lot of possibilities and the code can give TLE for large constraints. So we need to find a way to minimize our pool of possible points for K.

To optimize this approach, consider the below observations:

  • If we don’t consider the weights of each point, the required Point of minimum sum of distance will be around the center (of the polygon formed through given points).
  • However since the input is a list of points in the 2D plane, we cannot find the center directly. Instead, we will be using the Geometric Median.

geometric-median

  • Now to find the Minimum sum of distance for weighted points, we can modify this Median property to find the weighted center.

Step-by-Step Approach:

  • Store the x-coordinate and y-coordinate of all the N points separately in an array.
  • To find the x-coordinate of point K take the weighted median of all the x-coordinates of the N points.
  • Similarly, to find the y-coordinate of point K take the weighted median of all the y-coordinates of the points.
  • Now calculate the sum of the distance between point K and all the N points considering their weights.

Illustration:

  • To find the x-coordinate and y-coordinate of point K we will take the weighted median of the x-coordinates and y-coordinates of all the points respectively.
  • x-coordinate of point K will median of [1, 1, 4, 4, 4, 7, 7] which will be 4, and the y-coordinate of point K will median of [1, 1, 1, 4, 4, 7, 7] which will also be 4.
  • Point K will be (4,4)
  • The Sum of the Distance of point K from each point will be 21, which is the minimum sum of distance possible.

Below is the implementation of the above approach:

C++




#include <bits/stdc++.h>
using namespace std;
 
class GFG {
 
public:
    // Finds the median of an array
    int FindMedian(vector<int> cord)
    {
        int n = cord.size();
 
        // If size is odd then median is the middle element.
        if (n % 2 == 1) {
            return cord[n / 2];
        }
        // If size is even then median is mean of middle
        // elements.
        else {
            return (cord[n / 2] + cord[n / 2 - 1]) / 2;
        }
    }
 
    // To calculate minimum sum of distance between point k
    // and all other points
    int MinimizeSumOfDistance(int n,
                            vector<vector<int> > points,
                            vector<int> weights)
    {
        // Stores all x-coordinates of points
        vector<int> x_cord;
 
        // Stores all y-coordinates of points
        vector<int> y_cord;
 
        // Iterating through all the points
        for (int i = 0; i < n; i++) {
 
            // Each point is pushed into the array amount of time
            // equal to its weight
            for (int j = 0; j < weights[i]; j++) {
                x_cord.push_back(points[i][0]);
                y_cord.push_back(points[i][01]);
            }
        }
        // Sorting all the x-coordinates and y-coordinates
        sort(x_cord.begin(), x_cord.end());
        sort(y_cord.begin(), y_cord.end());
 
        // x-coordinate of point K
        int x = FindMedian(x_cord);
 
        // y-coordinate of point K
        int y = FindMedian(y_cord);
 
        // Stores the minimum sum of distance between point
        // K and all other points.
        int ans = 0;
 
        // To calculate minimum sum of distance iterate
        // through all the points.
        for (int i = 0; i < n; i++) {
            ans = ans
                + weights[i]
                        * (abs(x - points[i][0])
                        + abs(y - points[i][1]));
        }
        return ans;
    }
};
// Driver code
int main()
{
    GFG obj;
    // Number of points
    int n = 3;
 
    // Stores all the points
    vector<vector<int> > points{ { 1, 4 },
                                { 4, 1 },
                                { 7, 4 } };
 
    // Stores weights of each point
    vector<int> weights{ 2, 3, 2 };
 
    cout << obj.MinimizeSumOfDistance(n, points, weights);
    return 0;
}


Java




// Java code for the above approach
 
import java.util.*;
 
class GFG {
 
    // Finds the median of an array
    public int FindMedian(List<Integer> cord)
    {
        int n = cord.size();
 
        // If size is odd then median is the middle element.
        if (n % 2 == 1) {
            return cord.get(n / 2);
        }
        // If size is even then median is mean of middle
        // elements.
        else {
            return (cord.get(n / 2) + cord.get(n / 2 - 1))
                / 2;
        }
    }
 
    // To calculate minimum sum of distance between point k
    // and all other points
    public int
    MinimizeSumOfDistance(int n,
                          List<List<Integer> > points,
                          List<Integer> weights)
    {
        // Stores all x-coordinates of points
        List<Integer> x_cord = new ArrayList<>();
 
        // Stores all y-coordinates of points
        List<Integer> y_cord = new ArrayList<>();
 
        // Iterating through all the points
        for (int i = 0; i < n; i++) {
 
            // Each point is pushed into the array amount of
            // time equal to its weight
            for (int j = 0; j < weights.get(i); j++) {
                x_cord.add(points.get(i).get(0));
                y_cord.add(points.get(i).get(1));
            }
        }
        // Sorting all the x-coordinates and y-coordinates
        Collections.sort(x_cord);
        Collections.sort(y_cord);
 
        // x-coordinate of point K
        int x = FindMedian(x_cord);
 
        // y-coordinate of point K
        int y = FindMedian(y_cord);
 
        // Stores the minimum sum of distance between point
        // K and all other points.
        int ans = 0;
 
        // To calculate minimum sum of distance iterate
        // through all the points.
        for (int i = 0; i < n; i++) {
            ans = ans
                  + weights.get(i)
                        * (Math.abs(x
                                    - points.get(i).get(0))
                           + Math.abs(
                               y - points.get(i).get(1)));
        }
 
        return ans;
    }
    // Driver code
    public static void main(String[] args)
    {
        GFG obj = new GFG();
        // Number of points
        int n = 3;
 
        // Stores all the points
        List<List<Integer> > points = Arrays.asList(
            Arrays.asList(1, 4), Arrays.asList(4, 1),
            Arrays.asList(7, 4));
 
        // Stores weights of each point
        List<Integer> weights = Arrays.asList(2, 3, 2);
 
        System.out.println(
            obj.MinimizeSumOfDistance(n, points, weights));
    }
}
 
// This code is contributed by ragul21


Python3




# Finds the median of an array
def find_median(cord):
   
    n = len(cord)
 
    # If size is odd, median is the middle element
    if n % 2 == 1:
        return cord[n // 2]
 
    # If size is even, median is mean of middle elements
    else:
        return (cord[n // 2] + cord[n // 2 - 1]) / 2
 
# To calculate minimum sum of distance between point K and all other points
def minimize_sum_of_distance(n, points, weights):
   
    # Stores all x-coordinates of points
    x_cord = []
 
    # Stores all y-coordinates of points
    y_cord = []
 
    # Iterating through all the points
    for i in range(n):
        # Each point is pushed into the array amount of time equal to its weight
        for j in range(weights[i]):
            x_cord.append(points[i][0])
            y_cord.append(points[i][1])
 
    # Sorting all the x-coordinates and y-coordinates
    x_cord.sort()
    y_cord.sort()
 
    # x-coordinate of point K
    x = find_median(x_cord)
 
    # y-coordinate of point K
    y = find_median(y_cord)
 
    # Stores the minimum sum of distance between point K and all other points
    ans = 0
 
    # To calculate minimum sum of distance iterate through all the points
    for i in range(n):
        ans += weights[i] * (abs(x - points[i][0]) + abs(y - points[i][1]))
 
    return ans
 
 
# Driver code
if __name__ == "__main__":
    # Number of points
    n = 3
 
    # Stores all the points
    points = [[1, 4], [4, 1], [7, 4]]
 
    # Stores weights of each point
    weights = [2, 3, 2]
 
    print(minimize_sum_of_distance(n, points, weights))
     
#This code is contributed by Rohit Singh


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
class GFG
{
    // Finds the median of an array
    private int FindMedian(List<int> cord)
    {
        int n = cord.Count;
        if (n % 2 == 1)
        {
            return cord[n / 2];
        }
        // If size is even, then the median is the mean of middle elements.
        else
        {
            return (cord[n / 2] + cord[n / 2 - 1]) / 2;
        }
    }
    // To calculate the minimum sum of distance between
  // point k and all other points
    public int MinimizeSumOfDistance(int n, List<List<int>> points, List<int> weights)
    {
        // Stores all x-coordinates of points
        List<int> xCord = new List<int>();
        // Stores all y-coordinates of points
        List<int> yCord = new List<int>();
        // Iterating through all the points
        for (int i = 0; i < n; i++)
        {
            // Each point is pushed into the array
          // the number of times equal to its weight
            for (int j = 0; j < weights[i]; j++)
            {
                xCord.Add(points[i][0]);
                yCord.Add(points[i][1]);
            }
        }
        // Sorting all the x-coordinates and y-coordinates
        xCord.Sort();
        yCord.Sort();
 
        // x-coordinate of point K
        int x = FindMedian(xCord);
        // y-coordinate of point K
        int y = FindMedian(yCord);
        // Stores the minimum sum of distance between
      // point K and all other points
        int ans = 0;
        // To calculate the minimum sum of distance
      // iterate through all the points
        for (int i = 0; i < n; i++)
        {
            ans += weights[i] * (Math.Abs(x - points[i][0]) + Math.Abs(y - points[i][1]));
        }
 
        return ans;
    }
}
class Geek
{
    static void Main()
    {
        GFG obj = new GFG();
        // Number of points
        int n = 3;
        // Stores all the points
        List<List<int>> points = new List<List<int>>
        {
            new List<int> { 1, 4 },
            new List<int> { 4, 1 },
            new List<int> { 7, 4 }
        };
        // Stores weights of each point
        List<int> weights = new List<int> { 2, 3, 2 };
        Console.WriteLine(obj.MinimizeSumOfDistance(n, points, weights));
    }
}


Javascript




class GFG {
    Geek(cord) {
        const n = cord.length;
        // If size is odd, then median is the
        // middle element.
        if (n % 2 === 1) {
            return cord[Math.floor(n / 2)];
        }
        else {
            return Math.floor((cord[n / 2] + cord[n / 2 - 1]) / 2);
        }
    }
    // To calculate minimum sum of distance between
    // point k and all other points
    minimizeSumOfDistance(n, points, weights) {
        // Stores all x-coordinates of points
        const x_cord = [];
        const y_cord = [];
        // Iterating through all the points
        for (let i = 0; i < n; i++) {
            for (let j = 0; j < weights[i]; j++) {
                x_cord.push(points[i][0]);
                y_cord.push(points[i][1]);
            }
        }
        // Sorting all the x-coordinates and
        // y-coordinates
        x_cord.sort((a, b) => a - b);
        y_cord.sort((a, b) => a - b);
 
        // x-coordinate of point K
        const x = this.Geek(x_cord);
        const y = this.Geek(y_cord);
 
        // Stores the minimum sum of distance between point K and
        // all other points.
        let ans = 0;
        for (let i = 0; i < n; i++) {
            ans += weights[i] * (Math.abs(x - points[i][0]) + Math.abs(y - points[i][1]));
        }
        return ans;
    }
}
// Driver code
const obj = new GFG();
const n = 3;
// Stores all the points
const points = [
    [1, 4],
    [4, 1],
    [7, 4]
];
// Stores weights of each point
const weights = [2, 3, 2];
console.log(obj.minimizeSumOfDistance(n, points, weights));


Output

21








Time Complexity: O(M*logM), where M is the sum of all the weights of N points.

Auxiliary Space: O(M) 



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads