Check if a line at 45 degree can divide the plane into two equal weight parts

Given a set of n points (xi, yi) in 2D coordinate. Each point has some weight wi. The task is to check whether a line at 45 degree can be drawn so that sum of weights of points on each side are equal.

Examples:

Input : x1 = -1, y1 = 1, w1 = 3
x2 = -2, y2 = 1, w2 = 1
x3 = 1, y3 = -1, w3 = 4

Output : Yes


Input : x1 = 1, y1 = 1, w1 = 2
x2 = -1, y2 = 1, w2 = 1
x3 = 1, y3 = -1, w3 = 2

Output : No

First, let’s try to solve above problem for a vertical line i.e if a line x = i can divide the plane into two part such that the sum of weight at each side is equal.
Observe, multiple points with the same x-coordinate can be treated as one point with weight equal to the sum of weights of all points with the same x-coordinate.
Now, traverse through all x-coordinates from the minimum x-coordinate to maximum x-coordinate. So, make an array prefix_sum[], which will store the sum of weights till the point x = i.
So, there can be two options for which the answer can be ‘Yes’:

  • Either prefix_sum[1, 2, …, i-1] = prefix_sum[i+1, …, n]
  • or there exist a point i such that a line passes somewhere in between
    x = i and x = i+1 and prefix_sum[1, …, i] = prefix_sum[i+1, …, n],
    where prefix_sum[i, …, j] is the sum of weight of points from i to j.
int is_possible = false;
for (int i = 1; i < prefix_sum.size(); i++)
  if (prefix_sum[i] == total_sum - prefix_sum[i])
    is_possible = true
  
  if (prefix_sum[i-1] == total_sum - prefix_sum[i])
    is_possible = true

Now, to solve for a line at 45 degrees, we will rotate each point by 45 degrees.
Refer: 2D Transformation or Rotation of objects
So, point at (x, y), after 45 degree rotation will become ((x – y)/sqrt(2), (x + y)/sqrt(2)).
We can ignore the sqrt(2) since it is the scaling factor. Also, we don’t need to care about y-coordinate after rotation because a vertical line cannot distinguish between the point having the same x-coordinate. (x, y1) and (x, y2) will lie to the right, left or on any line of the form x = k.

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

#include <bits/stdc++.h>
using namespace std;
  
// Checking if a plane can be divide by a line
// at 45 degrees such that weight sum is equal
void is_partition_possible(int n, int x[],
                            int y[], int w[])
{
    map<int, int> weight_at_x;
    int max_x = -2e3, min_x = 2e3;
  
    // Rotating each point by 45 degrees and 
    // calculating prefix sum.
    // Also, finding maximum and minimum x
    // coordinates
    for (int i = 0; i < n; i++) {
        int new_x = x[i] - y[i];
        max_x = max(max_x, new_x);
        min_x = min(min_x, new_x);
  
        // storing weight sum upto x - y point
        weight_at_x[new_x] += w[i];
    }
  
    vector<int> sum_till;
    sum_till.push_back(0);
  
    // Finding prefix sum
    for (int x = min_x; x <= max_x; x++) {
        sum_till.push_back(sum_till.back() + 
                             weight_at_x[x]);
    }
  
    int total_sum = sum_till.back();
  
    int partition_possible = false;
    for (int i = 1; i < sum_till.size(); i++) {
        if (sum_till[i] == total_sum - sum_till[i])
            partition_possible = true;
  
        // Line passes through i, so it neither
        // falls left nor right.
        if (sum_till[i - 1] == total_sum - sum_till[i])
            partition_possible = true;
    }
  
    printf(partition_possible ? "YES\n" : "NO\n");
}
  
// Driven Program
int main()
{
    int n = 3;
    int x[] = { -1, -2, 1 };
    int y[] = { 1, 1, -1 };
    int w[] = { 3, 1, 4 };
    is_partition_possible(n, x, y, w);
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

import java.util.*;
  
// Checking if a plane can be divide by a line 
// at 45 degrees such that weight sum is equal
class GFG 
{
  
static void is_partition_possible(int n, int x[], 
                            int y[], int w[]) 
    Map<Integer, Integer> weight_at_x = new HashMap<Integer, Integer>(); 
    int max_x = (int) -2e3, min_x = (int) 2e3; 
  
    // Rotating each point by 45 degrees and 
    // calculating prefix sum. 
    // Also, finding maximum and minimum x 
    // coordinates 
    for (int i = 0; i < n; i++) 
    
        int new_x = x[i] - y[i]; 
        max_x = Math.max(max_x, new_x); 
        min_x = Math.min(min_x, new_x); 
  
        // storing weight sum upto x - y point 
        if(weight_at_x.containsKey(new_x))
        {
             weight_at_x.put(new_x, weight_at_x.get(new_x) + w[i]);
        }
        else
        {
            weight_at_x.put(new_x,w[i]);
        }
                  
        //weight_at_x[new_x] += w[i]; 
    
  
    Vector<Integer> sum_till = new Vector<>(); 
    sum_till.add(0); 
  
    // Finding prefix sum 
    for (int s = min_x; s <= max_x; s++) 
    
        if(weight_at_x.get(s) == null)
            sum_till.add(sum_till.lastElement());
        else
            sum_till.add(sum_till.lastElement() + 
                            weight_at_x.get(s)); 
    
  
    int total_sum = sum_till.lastElement(); 
  
    int partition_possible = 0
    for (int i = 1; i < sum_till.size(); i++)
    
        if (sum_till.get(i) == total_sum - sum_till.get(i)) 
            partition_possible = 1
  
        // Line passes through i, so it neither 
        // falls left nor right. 
        if (sum_till.get(i-1) == total_sum - sum_till.get(i)) 
            partition_possible = 1
    
  
    System.out.printf(partition_possible == 1 ? "YES\n" : "NO\n"); 
  
    // Driven code
    public static void main(String[] args) 
    {
        int n = 3
        int x[] = { -1, -2, 1 }; 
        int y[] = { 1, 1, -1 }; 
        int w[] = { 3, 1, 4 }; 
        is_partition_possible(n, x, y, w); 
    }
}
  
/* This code contributed by PrinciRaj1992 */

chevron_right


Output

Yes

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Recommended Posts:

    Article Tags :
    Practice Tags :


    Be the First to upvote.


    Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.