2167 - alee: Difference between revisions

From Bitnami MediaWiki
Pagină nouă: == Enunt == Parcul oraşului a fost neglijat mult timp, astfel că acum toate aleile sunt distruse. Prin urmare, anul acesta Primăria şi-a propus să facă reamenajări. Parcul are forma unui pătrat cu latura de n metri și este înconjurat de un gard care are exact două porți. Proiectanții de la Primărie au realizat o hartă a parcului și au trasat pe hartă un caroiaj care împarte parcul în nxn zone pătrate cu latura de 1 metru. Astfel harta parcului are aspectu...
 
No edit summary
 
Line 1: Line 1:
== Enunt ==
== Enunt ==


Parcul oraşului a fost neglijat mult timp, astfel că acum toate aleile sunt distruse. Prin urmare, anul acesta Primăria şi-a propus să facă reamenajări. Parcul are forma unui pătrat cu latura de n metri și este înconjurat de un gard care are exact două porți. Proiectanții de la Primărie au realizat o hartă a parcului și au trasat pe hartă un caroiaj care împarte parcul în nxn zone pătrate cu latura de 1 metru. Astfel harta parcului are aspectul unei matrice pătratice cu n linii și n coloane. Liniile și respectiv coloanele sunt numerotate de la 1 la n. Elementele matricei corespund zonelor pătrate de latură 1 metru. O astfel de zonă poate să conțină un copac sau este liberă. Edilii orașului doresc să paveze cu un număr minim de dale pătrate cu latura de 1 metru zonele libere (fără copaci) ale parcului, astfel încât să se obțină o alee continuă de la o poartă la alta.
Parcul oraşului a fost neglijat mult timp, astfel că acum toate aleile sunt distruse. Prin urmare, anul acesta Primăria şi-a propus să facă reamenajări. Parcul are forma unui pătrat cu latura de <code>n</code> metri și este înconjurat de un gard care are exact două porți. Proiectanții de la Primărie au realizat o hartă a parcului și au trasat pe hartă un caroiaj care împarte parcul în <code>nxn</code> zone pătrate cu latura de <code>1</code> metru. Astfel harta parcului are aspectul unei matrice pătratice cu <code>n</code> linii și <code>n</code> coloane. Liniile și respectiv coloanele sunt numerotate de la <code>1</code> la <code>n</code>. Elementele matricei corespund zonelor pătrate de latură <code>1</code> metru. O astfel de zonă poate să conțină un copac sau este liberă. Edilii orașului doresc să paveze cu un număr minim de dale pătrate cu latura de <code>1</code> metru zonele libere (fără copaci) ale parcului, astfel încât să se obțină o alee continuă de la o poartă la alta.
 
== Cerinta ==


= Cerința =
Scrieți un program care să determine numărul minim de dale necesare pentru construirea unei alei continue de la o poartă la cealaltă.
Scrieți un program care să determine numărul minim de dale necesare pentru construirea unei alei continue de la o poartă la cealaltă.


== Date de intrare ==
= Date de intrare =
 
Fișierul de intrare <code>aleeIN.txt</code> conține pe prima linie două valori naturale <code>n</code> și <code>m</code> separate printr-un spațiu, reprezentând dimensiunea parcului, respectiv numărul de copaci care se găsesc în parc. Fiecare dintre următoarele <code>m</code> linii conține câte două numere naturale <code>x</code> și <code>y</code> separate printr-un spațiu, reprezentând pozițiile copacilor în parc (<code>x</code> reprezintă linia, iar <code>y</code> reprezintă coloana zonei în care se află copacul). Ultima linie a fișierului conține patru numere naturale <code>x1 y1 x2 y2</code>, separate prin câte un spațiu, reprezentând pozițiile celor două porți (<code>x1</code>, <code>y1</code> reprezintă linia și respectiv coloana zonei ce conține prima poartă, iar <code>x2</code>, <code>y2</code> reprezintă linia și respectiv coloana zonei ce conține cea de a doua poartă).
Fișierul de intrare alee.in conține pe prima linie două valori naturale n și m separate printr-un spațiu, reprezentând dimensiunea parcului, respectiv numărul de copaci care se găsesc în parc. Fiecare dintre următoarele m linii conține câte două numere naturale x și y separate printr-un spațiu, reprezentând pozițiile copacilor în parc (x reprezintă linia, iar y reprezintă coloana zonei în care se află copacul). Ultima linie a fișierului conține patru numere naturale x1 y1 x2 y2, separate prin câte un spațiu, reprezentând pozițiile celor două porți (x1, y1 reprezintă linia și respectiv coloana zonei ce conține prima poartă, iar x2, y2 reprezintă linia și respectiv coloana zonei ce conține cea de a doua poartă).
 
== Date de ieșire ==


Fișierul de ieșire alee.out va conţine o singură linie pe care va fi scris un număr natural care reprezintă numărul minim de dale necesare pentru construirea aleii.
= Date de ieșire =
Fișierul de ieșire <code>aleeOUT.txt</code> va conţine o singură linie pe care va fi scris un număr natural care reprezintă numărul minim de dale necesare pentru construirea aleii. În cazul în care restricțiile nu sunt îndeplinite, se va afișa mesajul "Datele nu corespund restrictiilor impuse".


== Restricții și precizări ==
= Restricții și precizări =


*1 ≤ n ≤ 175
* <code>1 ≤ n ≤ 175</code>
*1 ≤ m < n*n
* <code>1 ≤ m < n*n</code>
*Aleea este continuă dacă oricare două plăci consecutive au o latură comună.
* Aleea este continuă dacă oricare două plăci consecutive au o latură comună.
*Aleea începe cu zona unde se găsește prima poartă și se termină cu zona unde se găsește cea de a doua poartă.
* Aleea începe cu zona unde se găsește prima poartă și se termină cu zona unde se găsește cea de a doua poartă.
*Pozițiile porților sunt distincte şi corespund unor zone libere.
* Pozițiile porților sunt distincte şi corespund unor zone libere.
*Pentru datele de test există întotdeauna soluție.
* Pentru datele de test există întotdeauna soluție.


== Exemplul 1 ==
= Exemplul 1: =
<code>aleeIN.txt</code>
8 6
2 7
3 3
4 6
5 4
7 3
7 5
1 1 8 8
<code>aleeOUT.txt</code>
15


;aleein.txt
=== Explicație ===
O modalitate de a construi aleea cu număr minim de dale este:


:8 6
<code>OOO-----</code>


:2 7
<code>--OO--x-</code>


:3 3
<code>--xO----</code>


:4 6
<code>---OOx--</code>


:5 4
<code>---xO---</code>


:7 3
<code>----OO--</code>


:7 5
<code>--x-xOO-</code>


:1 1 8 8
<code>------OO</code>


;aleeout.txt
(cu <code>X</code> am marcat copacii, cu <code>-</code> zonele libere, iar cu <code>O</code> dalele aleii).


:Datele introduse corespund restrictiilor impuse.
== Exemplul 2: ==
 
<code>aleeIN.txt</code>
:15
200 6
 
2 7
== Exemplul 2 ==
3 3
 
4 6
;aleein.txt
5 4
 
7 3
:88 67
7 5
 
1 1 8 8
:-1 -2
<code>aleeOUT.txt</code>
 
Datele nu corespund restrictiilor impuse
:-88 0
 
:5 -8
 
:-9 -7  
 
:-1 -2
 
:-7 6
 
:-2 0 9 23
 
;aleeout.txt
 
:Datele de intrare nu corespund restrictiilor impuse.


== Rezolvare ==
== Rezolvare ==


<syntaxhighlight lang="python3" line="1">
<syntaxhighlight lang="python3" line="1">
from collections import deque


import heapq
dx = [-1, 0, 0, 1]
 
dy = [0, -1, 1, 0]
def numar_dale_minim(parcul):
    n = len(parcul)
 
    # Găsim pozițiile porților
    poarta1 = None
    poarta2 = None
    for i in range(n):
        for j in range(n):
            if parcul[i][j] == 'P1':
                poarta1 = (i, j)
            elif parcul[i][j] == 'P2':
                poarta2 = (i, j)
 
    # Inițializăm distanțele cu infinit pentru toate nodurile
    distante = {(i, j): float('inf') for i in range(n) for j in range(n)}
    distante[poarta1] = 0
 
    # Utilizăm un heap pentru a selecta mereu nodul cu cea mai mică distanță
    heap = [(0, poarta1)]
 
    while heap:
        cost_curent, nod_curent = heapq.heappop(heap)
 
        if cost_curent > distante[nod_curent]:
            continue
 
        # Verificăm vecinii direcți
        for vecin in get_vecini(n, nod_curent[0], nod_curent[1]):
            cost_total = cost_curent + 1  # Costul este 1 pentru fiecare zonă pătrată
 
            if cost_total < distante[vecin]:
                distante[vecin] = cost_total
                heapq.heappush(heap, (cost_total, vecin))
 
    # Returnăm distanța până la poarta 2 (cea mai scurtă cale)
    return distante[poarta2]


def get_vecini(n, i, j):
def read():
    vecini = []
    global n, m, x1, y1, x2, y2, a
    with open("aleeIN.txt", "r") as f:
        n, m = map(int, f.readline().split())
        if not check_restrictions():
            return False
        a = [[0] * (n + 1) for _ in range(n + 1)]
        for _ in range(m):
            i, j = map(int, f.readline().split())
            a[i][j] = -1
        x1, y1, x2, y2 = map(int, f.readline().split())
    return True


     directii = [(-1, 0), (1, 0), (0, -1), (0, 1)]  # Sus, jos, stânga, dreapta
def check_restrictions():
     if not (1 <= n <= 175):
        with open("aleeOUT.txt", "w") as f:
            f.write("Datele nu corespund restrictiilor impuse\n")
        return False
    if not (1 <= m < n * n):
        with open("aleeOUT.txt", "w") as f:
            f.write("Datele nu corespund restrictiilor impuse\n")
        return False
    return True


    for di, dj in directii:
def OK(i, j):
        i_vecin, j_vecin = i + di, j + dj
    if i < 1 or i > n or j < 1 or j > n:
         if 0 <= i_vecin < n and 0 <= j_vecin < n:
         return False
            vecini.append((i_vecin, j_vecin))
    if a[i][j] == -1:
        return False
    return True


     return vecini
def lee():
     global a
    Q = deque([(x1, y1)])
    a[x1][y1] = 1
    while Q:
        i, j = Q.popleft()
        for k in range(4):
            ni = i + dx[k]
            nj = j + dy[k]
            if OK(ni, nj) and a[ni][nj] < 1:
                a[ni][nj] = a[i][j] + 1
                Q.append((ni, nj))


rezultat = numar_dale_minim(parcul)
def main():
print(rezultat)
    if not read():
        return
    lee()
    with open("aleeOUT.txt", "w") as f:
        f.write(str(a[x2][y2]) + "\n")


if __name__ == "__main__":
    main()


</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 20:26, 22 March 2024

Enunt[edit | edit source]

Parcul oraşului a fost neglijat mult timp, astfel că acum toate aleile sunt distruse. Prin urmare, anul acesta Primăria şi-a propus să facă reamenajări. Parcul are forma unui pătrat cu latura de n metri și este înconjurat de un gard care are exact două porți. Proiectanții de la Primărie au realizat o hartă a parcului și au trasat pe hartă un caroiaj care împarte parcul în nxn zone pătrate cu latura de 1 metru. Astfel harta parcului are aspectul unei matrice pătratice cu n linii și n coloane. Liniile și respectiv coloanele sunt numerotate de la 1 la n. Elementele matricei corespund zonelor pătrate de latură 1 metru. O astfel de zonă poate să conțină un copac sau este liberă. Edilii orașului doresc să paveze cu un număr minim de dale pătrate cu latura de 1 metru zonele libere (fără copaci) ale parcului, astfel încât să se obțină o alee continuă de la o poartă la alta.

Cerința[edit | edit source]

Scrieți un program care să determine numărul minim de dale necesare pentru construirea unei alei continue de la o poartă la cealaltă.

Date de intrare[edit | edit source]

Fișierul de intrare aleeIN.txt conține pe prima linie două valori naturale n și m separate printr-un spațiu, reprezentând dimensiunea parcului, respectiv numărul de copaci care se găsesc în parc. Fiecare dintre următoarele m linii conține câte două numere naturale x și y separate printr-un spațiu, reprezentând pozițiile copacilor în parc (x reprezintă linia, iar y reprezintă coloana zonei în care se află copacul). Ultima linie a fișierului conține patru numere naturale x1 y1 x2 y2, separate prin câte un spațiu, reprezentând pozițiile celor două porți (x1, y1 reprezintă linia și respectiv coloana zonei ce conține prima poartă, iar x2, y2 reprezintă linia și respectiv coloana zonei ce conține cea de a doua poartă).

Date de ieșire[edit | edit source]

Fișierul de ieșire aleeOUT.txt va conţine o singură linie pe care va fi scris un număr natural care reprezintă numărul minim de dale necesare pentru construirea aleii. Î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 ≤ 175
  • 1 ≤ m < n*n
  • Aleea este continuă dacă oricare două plăci consecutive au o latură comună.
  • Aleea începe cu zona unde se găsește prima poartă și se termină cu zona unde se găsește cea de a doua poartă.
  • Pozițiile porților sunt distincte şi corespund unor zone libere.
  • Pentru datele de test există întotdeauna soluție.

Exemplul 1:[edit | edit source]

aleeIN.txt

8 6 
2 7
3 3
4 6
5 4
7 3
7 5 
1 1 8 8

aleeOUT.txt

15

Explicație[edit | edit source]

O modalitate de a construi aleea cu număr minim de dale este:

OOO-----

--OO--x-

--xO----

---OOx--

---xO---

----OO--

--x-xOO-

------OO

(cu X am marcat copacii, cu - zonele libere, iar cu O dalele aleii).

Exemplul 2:[edit | edit source]

aleeIN.txt

200 6 
2 7
3 3
4 6
5 4
7 3
7 5 
1 1 8 8

aleeOUT.txt

Datele nu corespund restrictiilor impuse

Rezolvare[edit | edit source]

<syntaxhighlight lang="python3" line="1"> from collections import deque

dx = [-1, 0, 0, 1] dy = [0, -1, 1, 0]

def read():

   global n, m, x1, y1, x2, y2, a
   with open("aleeIN.txt", "r") as f:
       n, m = map(int, f.readline().split())
       if not check_restrictions():
           return False
       a = [[0] * (n + 1) for _ in range(n + 1)]
       for _ in range(m):
           i, j = map(int, f.readline().split())
           a[i][j] = -1
       x1, y1, x2, y2 = map(int, f.readline().split())
   return True

def check_restrictions():

   if not (1 <= n <= 175):
       with open("aleeOUT.txt", "w") as f:
           f.write("Datele nu corespund restrictiilor impuse\n")
       return False
   if not (1 <= m < n * n):
       with open("aleeOUT.txt", "w") as f:
           f.write("Datele nu corespund restrictiilor impuse\n")
       return False
   return True

def OK(i, j):

   if i < 1 or i > n or j < 1 or j > n:
       return False
   if a[i][j] == -1:
       return False
   return True

def lee():

   global a
   Q = deque([(x1, y1)])
   a[x1][y1] = 1
   while Q:
       i, j = Q.popleft()
       for k in range(4):
           ni = i + dx[k]
           nj = j + dy[k]
           if OK(ni, nj) and a[ni][nj] < 1:
               a[ni][nj] = a[i][j] + 1
               Q.append((ni, nj))

def main():

   if not read():
       return
   lee()
   with open("aleeOUT.txt", "w") as f:
       f.write(str(a[x2][y2]) + "\n")

if __name__ == "__main__":

   main()

</syntaxhighlight>