Compruebe si una línea a 45 grados puede dividir el avión en dos partes de igual peso

Dado un conjunto de n puntos (x i , y i ) en coordenadas 2D. Cada punto tiene un peso w i . La tarea es verificar si se puede dibujar una línea a 45 grados para que la suma de los pesos de los puntos en cada lado sea igual.
Ejemplos: 
 

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

Primero, intentemos resolver el problema anterior para una línea vertical, es decir, si una línea x = i puede dividir el plano en dos partes, de modo que la suma del peso en cada lado sea igual. 
Observe que varios puntos con la misma coordenada x se pueden tratar como un punto con un peso igual a la suma de los pesos de todos los puntos con la misma coordenada x. 
Ahora, recorra todas las coordenadas x desde la coordenada x mínima hasta la coordenada x máxima. Por lo tanto, cree una array prefix_sum[] , que almacenará la suma de los pesos hasta el punto x = i
Entonces, puede haber dos opciones para las cuales la respuesta puede ser ‘Sí’: 
 

  • Prefix_sum[1, 2, …, i-1] = prefix_sum[i+1, …, n] 
     
  • o existe un punto i tal que una línea pasa en algún lugar entre 
    x = i y x = i+1 y suma_prefijo[1, …, i] = suma_prefijo[i+1, …, n], 
    donde suma_prefijo[i, … , j] es la suma de los pesos de los puntos de i a 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

Ahora, para resolver una línea a 45 grados, rotaremos cada punto 45 grados. 
Consulte: Transformación 2D o Rotación de objetos 
Entonces, apunte a (x, y), después de una rotación de 45 grados se convertirá en ((x – y)/sqrt(2), (x + y)/sqrt(2)). 
Podemos ignorar el sqrt(2) ya que es el factor de escala. Además, no necesitamos preocuparnos por la coordenada y después de la rotación porque una línea vertical no puede distinguir entre el punto que tiene la misma coordenada x. (x, y 1 ) y (x, y 2 ) estarán a la derecha, a la izquierda o en cualquier línea de la forma x = k. 
 

C++

#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;
}

Java

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 */

Python3

from collections import defaultdict
 
# Checking if a plane can be divide by a line
# at 45 degrees such that weight sum is equal
def is_partition_possible(n, x, y, w):
    weight_at_x = defaultdict(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 i in range(n):
        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]
    sum_till = []
    sum_till.append(0)
 
    # Finding prefix sum
    for x in range(min_x, max_x + 1):
        sum_till.append(sum_till[-1] +
                        weight_at_x[x])
    total_sum = sum_till[-1]
    partition_possible = False
    for i in range(1, len(sum_till)):
        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
    if partition_possible:
        print("YES")
    else:
        print("NO")
 
# Driven Program
if __name__ == "__main__":
 
    n = 3
    x = [-1, -2, 1]
    y = [1, 1, -1]
    w = [3, 1, 4]
    is_partition_possible(n, x, y, w)
 
    # This code is contributed by chitranayal.

C#

// Checking if a plane can be divide by a line
// at 45 degrees such that weight sum is equal
using System;
using System.Collections.Generic;
 
public class GFG{
     
    static void is_partition_possible(int n, int[] x, int[] y, int[] w)
    {
        Dictionary<int,int> weight_at_x = new Dictionary<int,int>();
        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[new_x]+=w[i];
            }
            else
            {
                weight_at_x.Add(new_x,w[i]);
            }
                      
            // weight_at_x[new_x] += w[i];
             
        }
        List<int> sum_till = new List<int>();
        sum_till.Add(0);
         
        // Finding prefix sum
        for (int s = min_x; s <= max_x; s++)
        {
            if(!weight_at_x.ContainsKey(s))
            {
                sum_till.Add(sum_till[sum_till.Count - 1]);
            }
           else
           {
               sum_till.Add(sum_till[sum_till.Count-1] + weight_at_x[s]);
           }
        }
        int total_sum = sum_till[sum_till.Count-1];
        int partition_possible = 0;
        for (int i = 1; i < sum_till.Count; i++)
        {
            if (sum_till[i] == total_sum - sum_till[i])
                partition_possible = 1;
             
            // Line passes through i, so it neither
            // falls left nor right.
            if (sum_till[i-1] == total_sum - sum_till[i])
                partition_possible = 1;
        }
        Console.WriteLine(partition_possible == 1 ? "YES" : "NO");
    }
   
    // Driven code
    static public void 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);
    }
}
 
// This code is contributed by rag2127

Javascript

<script>
 
// Checking if a plane can be divide by a line
// at 45 degrees such that weight sum is equal
     
    function is_partition_possible(n,x,y,w)
    {
        let weight_at_x = new Map();
    let max_x = -2e3, min_x =  2e3;
  
    // Rotating each point by 45 degrees and
    // calculating prefix sum.
    // Also, finding maximum and minimum x
    // coordinates
    for (let i = 0; i < n; i++)
    {
        let 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.has(new_x))
        {
             weight_at_x.set(new_x, weight_at_x.get(new_x)
             + w[i]);
        }
        else
        {
            weight_at_x.set(new_x,w[i]);
        }
                  
        //weight_at_x[new_x] += w[i];
    }
  
    let sum_till = [];
    sum_till.push(0);
  
    // Finding prefix sum
    for (let s = min_x; s <= max_x; s++)
    {
        if(weight_at_x.get(s) == null)
            sum_till.push(sum_till[sum_till.length-1]);
        else
            sum_till.push(sum_till[sum_till.length-1] +
                            weight_at_x.get(s));
    }
  
    let total_sum = sum_till[sum_till.length-1];
  
    let partition_possible = 0;
    for (let i = 1; i < sum_till.length; i++)
    {
        if (sum_till[i] == total_sum - sum_till[i])
            partition_possible = 1;
  
        // Line passes through i, so it neither
        // falls left nor right.
        if (sum_till[i-1] == total_sum - sum_till[i])
            partition_possible = 1;
    }
  
    document.write(partition_possible == 1 ? "YES\n" : "NO\n");
    }
     
    // Driven code
    let n = 3;
    let x=[ -1, -2, 1 ];
    let y=[1, 1, -1 ];
    let w=[ 3, 1, 4 ];
    is_partition_possible(n, x, y, w);
     
         
 
 
// This code is contributed by avanitrachhadiya2155
 
</script>

Producción: 

Yes

Complejidad de tiempo : O(nlogn + max) donde max = 4*10 3
Espacio auxiliar : O(n + max)
 

Publicación traducida automáticamente

Artículo escrito por anuj0503 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *