Minimize Sum of Distance in 2D Plane
Last Updated :
26 Oct, 2023
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|.
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.
- 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 :
int FindMedian(vector< int > cord)
{
int n = cord.size();
if (n % 2 == 1) {
return cord[n / 2];
}
else {
return (cord[n / 2] + cord[n / 2 - 1]) / 2;
}
}
int MinimizeSumOfDistance( int n,
vector<vector< int > > points,
vector< int > weights)
{
vector< int > x_cord;
vector< int > y_cord;
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < weights[i]; j++) {
x_cord.push_back(points[i][0]);
y_cord.push_back(points[i][01]);
}
}
sort(x_cord.begin(), x_cord.end());
sort(y_cord.begin(), y_cord.end());
int x = FindMedian(x_cord);
int y = FindMedian(y_cord);
int ans = 0;
for ( int i = 0; i < n; i++) {
ans = ans
+ weights[i]
* ( abs (x - points[i][0])
+ abs (y - points[i][1]));
}
return ans;
}
};
int main()
{
GFG obj;
int n = 3;
vector<vector< int > > points{ { 1, 4 },
{ 4, 1 },
{ 7, 4 } };
vector< int > weights{ 2, 3, 2 };
cout << obj.MinimizeSumOfDistance(n, points, weights);
return 0;
}
|
Java
import java.util.*;
class GFG {
public int FindMedian(List<Integer> cord)
{
int n = cord.size();
if (n % 2 == 1 ) {
return cord.get(n / 2 );
}
else {
return (cord.get(n / 2 ) + cord.get(n / 2 - 1 ))
/ 2 ;
}
}
public int
MinimizeSumOfDistance( int n,
List<List<Integer> > points,
List<Integer> weights)
{
List<Integer> x_cord = new ArrayList<>();
List<Integer> y_cord = new ArrayList<>();
for ( int i = 0 ; i < n; i++) {
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 ));
}
}
Collections.sort(x_cord);
Collections.sort(y_cord);
int x = FindMedian(x_cord);
int y = FindMedian(y_cord);
int ans = 0 ;
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;
}
public static void main(String[] args)
{
GFG obj = new GFG();
int n = 3 ;
List<List<Integer> > points = Arrays.asList(
Arrays.asList( 1 , 4 ), Arrays.asList( 4 , 1 ),
Arrays.asList( 7 , 4 ));
List<Integer> weights = Arrays.asList( 2 , 3 , 2 );
System.out.println(
obj.MinimizeSumOfDistance(n, points, weights));
}
}
|
Python3
def find_median(cord):
n = len (cord)
if n % 2 = = 1 :
return cord[n / / 2 ]
else :
return (cord[n / / 2 ] + cord[n / / 2 - 1 ]) / 2
def minimize_sum_of_distance(n, points, weights):
x_cord = []
y_cord = []
for i in range (n):
for j in range (weights[i]):
x_cord.append(points[i][ 0 ])
y_cord.append(points[i][ 1 ])
x_cord.sort()
y_cord.sort()
x = find_median(x_cord)
y = find_median(y_cord)
ans = 0
for i in range (n):
ans + = weights[i] * ( abs (x - points[i][ 0 ]) + abs (y - points[i][ 1 ]))
return ans
if __name__ = = "__main__" :
n = 3
points = [[ 1 , 4 ], [ 4 , 1 ], [ 7 , 4 ]]
weights = [ 2 , 3 , 2 ]
print (minimize_sum_of_distance(n, points, weights))
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class GFG
{
private int FindMedian(List< int > cord)
{
int n = cord.Count;
if (n % 2 == 1)
{
return cord[n / 2];
}
else
{
return (cord[n / 2] + cord[n / 2 - 1]) / 2;
}
}
public int MinimizeSumOfDistance( int n, List<List< int >> points, List< int > weights)
{
List< int > xCord = new List< int >();
List< int > yCord = new List< int >();
for ( int i = 0; i < n; i++)
{
for ( int j = 0; j < weights[i]; j++)
{
xCord.Add(points[i][0]);
yCord.Add(points[i][1]);
}
}
xCord.Sort();
yCord.Sort();
int x = FindMedian(xCord);
int y = FindMedian(yCord);
int ans = 0;
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();
int n = 3;
List<List< int >> points = new List<List< int >>
{
new List< int > { 1, 4 },
new List< int > { 4, 1 },
new List< int > { 7, 4 }
};
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 (n % 2 === 1) {
return cord[Math.floor(n / 2)];
}
else {
return Math.floor((cord[n / 2] + cord[n / 2 - 1]) / 2);
}
}
minimizeSumOfDistance(n, points, weights) {
const x_cord = [];
const y_cord = [];
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]);
}
}
x_cord.sort((a, b) => a - b);
y_cord.sort((a, b) => a - b);
const x = this .Geek(x_cord);
const y = this .Geek(y_cord);
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;
}
}
const obj = new GFG();
const n = 3;
const points = [
[1, 4],
[4, 1],
[7, 4]
];
const weights = [2, 3, 2];
console.log(obj.minimizeSumOfDistance(n, points, weights));
|
Time Complexity: O(M*logM), where M is the sum of all the weights of N points.
Auxiliary Space: O(M)
Share your thoughts in the comments
Please Login to comment...