2861 - puncte4: Difference between revisions

From Bitnami MediaWiki
Pagină nouă: == Enunt == Zăhărel a desenat pe o foaie de hârtie N puncte în plan. Curios din fire, şi-a ales încă M puncte pe axa OX şi s-a întrebat pentru fiecare dintre cele M puncte de pe axa Ox care dintre cele N puncte este cel mai apropiat (situat la distanță minimă). Se consideră că distanța dintre două puncte (x1, y1) şi (x2, y2) este (x1-x2)2 + (y1-y2)2. == Cerința == Scrieți un program pentru Zăhărel care să determine pentru fiecare dintre cele M puncte...
 
No edit summary
 
Line 1: Line 1:
== Enunt ==  
== Enunt ==  


Zăhărel a desenat pe o foaie de hârtie N puncte în plan. Curios din fire, şi-a ales încă M puncte pe axa OX şi s-a întrebat pentru fiecare dintre cele M puncte de pe axa Ox care dintre cele N puncte este cel mai apropiat (situat la distanță minimă). Se consideră că distanța dintre două puncte (x1, y1) şi (x2, y2) este (x1-x2)2 + (y1-y2)2.
Zăhărel a desenat pe o foaie de hârtie <code>N</code> puncte în plan. Curios din fire, şi-a ales încă <code>M</code> puncte pe axa <code>OX</code> şi s-a întrebat pentru fiecare dintre cele <code>M</code> puncte de pe axa <code>Ox</code> care dintre cele <code>N</code> puncte este cel mai apropiat (situat la distanță minimă). Se consideră că distanța dintre două puncte <code>(x1, y1)</code> şi <code>(x2, y2)</code> este <code>(x1-x2)^2</code> <code>+ (y1-y2)^2</code>.


== Cerința ==
= Cerința =
Scrieți un program pentru Zăhărel care să determine pentru fiecare dintre cele <code>M</code> puncte de pe axa <code>OX</code>, care este distanța la cel mai apropiat punct dintre cele <code>N</code> desenate pe hârtie.


Scrieți un program pentru Zăhărel care să determine pentru fiecare dintre cele M puncte de pe axa OX, care este distanța la cel mai apropiat punct dintre cele N desenate pe hârtie.
= Date de intrare =
Fișierul de intrare <code>puncte4IN.txt</code> conține pe prima linie numerele naturale <code>N</code>, <code>M</code> separate prin spații. Fiecare dintre următoarele <code>N</code> linii conține câte o pereche de numere naturale nenule <code>x y</code>, separate prin spații, reprezentând coordonatele celor <code>N</code> puncte (în ordinea abscisă, ordonată). Fiecare dintre următoarele <code>M</code> linii conține câte un număr natural <code>x</code>, reprezentând abscisele (coordonatele pe axa <code>OX</code>) ale celor <code>M</code> puncte.


== Date de intrare ==
= Date de ieșire =
Fișierul de ieșire <code>puncte4OUT.txt</code> va conține <code>M</code> linii. Pe linia <code>i</code> va fi scris un număr natural reprezentând distanța la cel mai apropiat punct dintre cele <code>N</code> de pe hârtie pentru al <code>i</code>-lea punct de pe axa <code>OX</code> (considerând ordinea punctelor din fișierul de intrare). În cazul în care restricțiile nu sunt îndeplinite, se va afișa mesajul "Datele nu corespund restrictiilor impuse".


Fișierul de intrare puncte4.in conține pe prima linie numerele naturale N, M separate prin spații. Fiecare dintre următoarele N linii conține câte o pereche de numere naturale nenule x y, separate prin spații, reprezentând coordonatele celor N puncte (în ordinea abscisă, ordonată). Fiecare dintre următoarele M linii conține câte un număr natural x, reprezentând abscisele (coordonatele pe axa OX) ale celor M puncte.
= Restricții și precizări =


== Date de ieșire ==
* <code>1 ≤ N ≤ 100.000</code>
* <code>1 ≤ M ≤ 200.000</code>
* Toate coordonatele din fișierul de intrare sunt numere naturale din intervalul <code>[1, 1.000.000.000]</code>
* Cele <code>N</code> puncte din fișierul de intrare sunt sortate după coordonata <code>x</code> crescător, iar în cazul în care două puncte au aceeași abscisă, ele sunt ordonate crescător după coordonata <code>y</code>.
* Pentru <code>50%</code> din teste <code>N ≥ 90000</code> și <code>M ≥ 150000</code>.


Fișierul de ieșire puncte4.out va conține M linii. Pe linia i va fi scris un număr natural reprezentând distanța la cel mai apropiat punct dintre cele N de pe hârtie pentru al i-lea punct de pe axa OX (considerând ordinea punctelor din fișierul de intrare).
= Exemplul 1: =
<code>puncte4IN.txt</code>
3 2
1 1
5 1
10 2
2
7
<code>puncte4OUT.txt</code>
2
5


== Restrictii si precizari ==
=== Explicație ===
Pe hârtie au fost desenate <code>3</code> puncte, având coordonatele <code>(1,1)</code>, <code>(5,1)</code>, respectiv <code>(10,2)</code>. Pe axa <code>OX</code> se află <code>2</code> puncte, având abscisa <code>2</code>, respectiv <code>7</code>.


*1 ≤ N ≤ 100.000
Distanța minimă dintre punctul de pe axa <code>OX</code> de abscisă <code>2</code> este <code>2</code> (cel mai apropiat punct fiind cel de coordonate <code>(1,1)</code>).


*1 ≤ M ≤ 200.000
Distanța minimă dintre punctul de pe axa <code>OX</code> de abscisă <code>7</code> este <code>5</code> (cel mai apropiat punct fiind cel de coordonate <code>(5,1)</code>).


*Toate coordonatele din fișierul de intrare sunt numere naturale din intervalul [1, 1.000.000.000]
== Exemplul 2: ==
 
<code>puncte4IN.txt</code>
*Cele N puncte din fișierul de intrare sunt sortate după coordonata x crescător, iar în cazul în care două puncte au aceeași abscisă, ele sunt ordonate crescător după coordonata y.
100001 2
 
1 1  
*Pentru 50% din teste N ≥ 90000 și M ≥ 150000.
5 1
 
10 2
== Exemlul 1 ==
2
 
7
; intrare
<code>puncte4OUT.txt</code>
 
Datele nu corespund restrictiilor impuse
:3 2
 
:1 1  
 
:5 1
 
:10 2
 
:2
 
:7
 
; iesire
 
:Datele introduse corespund restrictiilor impuse.
 
:2
 
:5
 
== Exemplul 2 ==
 
; intrare
 
:-1 -9
 
:0 0
 
:11 16
 
:-7 -9
 
:3
 
:2
 
; iesire
 
:Datele de intrare nu corespund restrictiilor impuse.


== Rezolvare ==
== Rezolvare ==
<syntaxhighlight lang="python3" line="1">
<syntaxhighlight lang="python3" line="1">
from typing import List, Tuple


#2861 - puncte4
# Constante
MAX_N = 100005
INF = float('inf')


import math
# Definirea tipului punct ca un tuplu de două întregi
Point = Tuple[int, int]


def distanta_puncte(punct1, punct2):
# Funcția pentru calculul punctului de întâlnire între două puncte
     return (punct1[0] - punct2[0])**2 + (punct1[1] - punct2[1])**2
def meet(a: Point, b: Point) -> int:
     if a[0] == b[0]:
        return INF if a[1] < b[1] else 0
    x = (a[0]**2 + a[1]**2 - b[0]**2 - b[1]**2)
    x = (x + 2 * (a[0] - b[0]) - 1) // (2 * (a[0] - b[0]))
    return max(0, min(int(x), INF))


def cel_mai_apropiat_punct(punct_ox, lista_puncte):
# Funcția pentru verificarea restricțiilor
     dist_minima = float('inf')
def verifica_restricții(N: int, M: int, puncte: List[Point]) -> bool:
    punct_apropiat = None
     if not (1 <= N <= 100000) or not (1 <= M <= 200000):
 
        return False
     for punct in lista_puncte:
     for x, y in puncte:
         distanta = distanta_puncte(punct_ox, punct)
         if not (1 <= x <= 1000000000) or not (1 <= y <= 1000000000):
        if distanta < dist_minima:
             return False
             dist_minima = distanta
     return True
            punct_apropiat = punct
 
     return math.sqrt(dist_minima)


# Funcția principală
def main():
def main():
     # Citeste numarul de puncte N
     with open("puncte4IN.txt", "r") as fin, open("puncte4OUT.txt", "w") as fout:
    N = int(input("Introduceti numarul de puncte pe hârtie: "))
         N, M = map(int, fin.readline().split())
 
         P = [tuple(map(int, fin.readline().split())) for _ in range(N)]
    # Citeste coordonatele punctelor N
       
    puncte_hartie = []
        # Verificarea restricțiilor
    for i in range(N):
        if not verifica_restricții(N, M, P):
         x, y = map(int, input(f"Introduceti coordonatele punctului {i + 1} (x y): ").split())
            fout.write("Datele nu corespund restrictiilor impuse\n")
         puncte_hartie.append((x, y))
            return
 
    # Citeste numarul de puncte M de pe axa OX
    M = int(input("Introduceti numarul de puncte de pe axa OX: "))


    # Citeste coordonatele punctelor de pe axa OX
        X = [0] + [INF] * N
    puncte_ox = [int(input(f"Introduceti coordonata punctului de pe axa OX {i + 1}: ")) for i in range(M)]
        stk = [0]
       
        for i in range(1, N):
            while stk and (x := meet(P[stk[-1]], P[i])) <= X[len(stk)-1]:
                stk.pop()
            stk.append(i)
            X[len(stk)-1] = x
            X[len(stk)] = INF


    # Determina distanta la cel mai apropiat punct pentru fiecare punct de pe axa OX
        for _ in range(M):
    for punct_ox in puncte_ox:
            x = int(fin.readline())
        distanta_minima = cel_mai_apropiat_punct((punct_ox, 0), puncte_hartie)
            i = next(i for i in range(len(stk)) if X[i] > x) - 1
        print(f"Pt punctul de pe axa OX {punct_ox}, distanta la cel mai apropiat punct este {distanta_minima}")
            result = (x - P[stk[i]][0])**2 + P[stk[i]][1]**2
            fout.write(f"{result}\n")


# Executarea programului
if __name__ == "__main__":
if __name__ == "__main__":
     main()
     main()


</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 20:33, 23 February 2024

Enunt[edit | edit source]

Zăhărel a desenat pe o foaie de hârtie N puncte în plan. Curios din fire, şi-a ales încă M puncte pe axa OX şi s-a întrebat pentru fiecare dintre cele M puncte de pe axa Ox care dintre cele N puncte este cel mai apropiat (situat la distanță minimă). Se consideră că distanța dintre două puncte (x1, y1) şi (x2, y2) este (x1-x2)^2 + (y1-y2)^2.

Cerința[edit | edit source]

Scrieți un program pentru Zăhărel care să determine pentru fiecare dintre cele M puncte de pe axa OX, care este distanța la cel mai apropiat punct dintre cele N desenate pe hârtie.

Date de intrare[edit | edit source]

Fișierul de intrare puncte4IN.txt conține pe prima linie numerele naturale N, M separate prin spații. Fiecare dintre următoarele N linii conține câte o pereche de numere naturale nenule x y, separate prin spații, reprezentând coordonatele celor N puncte (în ordinea abscisă, ordonată). Fiecare dintre următoarele M linii conține câte un număr natural x, reprezentând abscisele (coordonatele pe axa OX) ale celor M puncte.

Date de ieșire[edit | edit source]

Fișierul de ieșire puncte4OUT.txt va conține M linii. Pe linia i va fi scris un număr natural reprezentând distanța la cel mai apropiat punct dintre cele N de pe hârtie pentru al i-lea punct de pe axa OX (considerând ordinea punctelor din fișierul de intrare). În cazul în care restricțiile nu sunt îndeplinite, se va afișa mesajul "Datele nu corespund restrictiilor impuse".

Restricții și precizări[edit | edit source]

  • 1 ≤ N ≤ 100.000
  • 1 ≤ M ≤ 200.000
  • Toate coordonatele din fișierul de intrare sunt numere naturale din intervalul [1, 1.000.000.000]
  • Cele N puncte din fișierul de intrare sunt sortate după coordonata x crescător, iar în cazul în care două puncte au aceeași abscisă, ele sunt ordonate crescător după coordonata y.
  • Pentru 50% din teste N ≥ 90000 și M ≥ 150000.

Exemplul 1:[edit | edit source]

puncte4IN.txt

3 2
1 1 
5 1
10 2
2
7

puncte4OUT.txt

2
5

Explicație[edit | edit source]

Pe hârtie au fost desenate 3 puncte, având coordonatele (1,1), (5,1), respectiv (10,2). Pe axa OX se află 2 puncte, având abscisa 2, respectiv 7.

Distanța minimă dintre punctul de pe axa OX de abscisă 2 este 2 (cel mai apropiat punct fiind cel de coordonate (1,1)).

Distanța minimă dintre punctul de pe axa OX de abscisă 7 este 5 (cel mai apropiat punct fiind cel de coordonate (5,1)).

Exemplul 2:[edit | edit source]

puncte4IN.txt

100001 2
1 1 
5 1
10 2
2
7

puncte4OUT.txt

Datele nu corespund restrictiilor impuse

Rezolvare[edit | edit source]

<syntaxhighlight lang="python3" line="1"> from typing import List, Tuple

  1. Constante

MAX_N = 100005 INF = float('inf')

  1. Definirea tipului punct ca un tuplu de două întregi

Point = Tuple[int, int]

  1. Funcția pentru calculul punctului de întâlnire între două puncte

def meet(a: Point, b: Point) -> int:

   if a[0] == b[0]:
       return INF if a[1] < b[1] else 0
   x = (a[0]**2 + a[1]**2 - b[0]**2 - b[1]**2)
   x = (x + 2 * (a[0] - b[0]) - 1) // (2 * (a[0] - b[0]))
   return max(0, min(int(x), INF))
  1. Funcția pentru verificarea restricțiilor

def verifica_restricții(N: int, M: int, puncte: List[Point]) -> bool:

   if not (1 <= N <= 100000) or not (1 <= M <= 200000):
       return False
   for x, y in puncte:
       if not (1 <= x <= 1000000000) or not (1 <= y <= 1000000000):
           return False
   return True
  1. Funcția principală

def main():

   with open("puncte4IN.txt", "r") as fin, open("puncte4OUT.txt", "w") as fout:
       N, M = map(int, fin.readline().split())
       P = [tuple(map(int, fin.readline().split())) for _ in range(N)]
       
       # Verificarea restricțiilor
       if not verifica_restricții(N, M, P):
           fout.write("Datele nu corespund restrictiilor impuse\n")
           return
       X = [0] + [INF] * N
       stk = [0]
       
       for i in range(1, N):
           while stk and (x := meet(P[stk[-1]], P[i])) <= X[len(stk)-1]:
               stk.pop()
           stk.append(i)
           X[len(stk)-1] = x
           X[len(stk)] = INF
       for _ in range(M):
           x = int(fin.readline())
           i = next(i for i in range(len(stk)) if X[i] > x) - 1
           result = (x - P[stk[i]][0])**2 + P[stk[i]][1]**2
           fout.write(f"{result}\n")
  1. Executarea programului

if __name__ == "__main__":

   main()

</syntaxhighlight>