1337 - Susan: Difference between revisions

From Bitnami MediaWiki
Pagină nouă: == Cerinta == Eroul nostru Susan se află într-un turn de formă cubică, de latură n. El dorește să ajungă la comoara ascunsă în interiorul turnului. Din fericire, Susan a făcut rost de o hartă care îi indică cu exactitate coordonatele locului în care se află comoara din turn. Eroul nostru vrea să știe care este distanța minimă pe care o poate parcurge pentru a ajunge la comoară. Turnul este împărțit în n etaje, iar fiecare etaj este împărțit în...
 
No edit summary
 
Line 1: Line 1:
== Cerinta ==  
== Cerinta ==  


Eroul nostru Susan se află într-un turn de formă cubică, de latură n. El dorește să ajungă la comoara ascunsă în interiorul turnului. Din fericire, Susan a făcut rost de o hartă care îi indică cu exactitate coordonatele locului în care se află comoara din turn. Eroul nostru vrea să știe care este distanța minimă pe care o poate parcurge pentru a ajunge la comoară.
Eroul nostru Susan se află într-un turn de formă cubică, de latură <code>n</code>. El dorește să ajungă la comoara ascunsă în interiorul turnului. Din fericire, Susan a făcut rost de o hartă care îi indică cu exactitate coordonatele locului în care se află comoara din turn. Eroul nostru vrea să știe care este distanța minimă pe care o poate parcurge pentru a ajunge la comoară.


Turnul este împărțit în n etaje, iar fiecare etaj este împărțit în n x n celule (camere). O cameră poate:
Turnul este împărțit în <code>n</code> etaje, iar fiecare etaj este împărțit în <code>n x n</code> celule (camere). O cameră poate:
*fi blocată, astfel fiind inaccesibilă eroului nostru
 
*fi accesibilă, astfel eroul nostru poate intra în aceasta
* fi blocată, astfel fiind inaccesibilă eroului nostru
*conține o scară ascendentă care îl poate duce pe erou cu un etaj mai sus, în camera situată deasupra camerei curente
* fi accesibilă, astfel eroul nostru poate intra în aceasta
*conține o scară descendentă care îl poate duce pe erou cu un etaj mai jos, în camera situată sub camera curentă
* conține o scară ascendentă care îl poate duce pe erou cu un etaj mai sus, în camera situată deasupra camerei curente
*conține o trapă prin care eroul va cădea la etajul inferior, în camerele situate sub camera curentă (dacă eroul, în urma căderii, se află într-o cameră ce conține o trapă, el va continua *să cadă până se va afla într-o o cameră fără trapă, pe aceeași coloană)
* conține o scară descendentă care îl poate duce pe erou cu un etaj mai jos, în camera situată sub camera curentă
* conține o trapă prin care eroul va cădea la etajul inferior, în camerele situate sub camera curentă (dacă eroul, în urma căderii, se află într-o cameră ce conține o trapă, el va continua să cadă până se va afla într-o o cameră fără trapă, pe aceeași coloană)


La fiecare trecere dintr-o cameră în alta, eroul execută un pas.
La fiecare trecere dintr-o cameră în alta, eroul execută un pas.
Line 14: Line 15:
Fiind date latura turnului și coordonatele zidurilor, scărilor, gropilor, eroului și a comorii, se cere să se afișeze numărul minim de pași pe care îl poate parcurge Susan pentru a ajunge la comoară.
Fiind date latura turnului și coordonatele zidurilor, scărilor, gropilor, eroului și a comorii, se cere să se afișeze numărul minim de pași pe care îl poate parcurge Susan pentru a ajunge la comoară.


== Date de intrare ==
= Date de intrare =
 
Fișierul de intrare <code>turnIN.txt</code> conține:
Fișierul de intrare turn.in conține:
 
*pe prima linie numărul n, reprezentând lungimea laturii turnului.
*pe a doua linie se află numărul z, reprezentând numărul de ziduri, numărul s1, reprezentând numărul de scări descendente, numărul s2, reprezentând numărul de scări descendente și numărul g, reprezentând numărul de gropi.
*pe următoarele z linii se află coordonatele zidurilor.
*pe următoarele s1 linii se află coordonatele scărilor ascendente.
*pe următoarele s2 linii se află coordonatele scărilor descendente.
*pe următoarele g linii se află coordonatele gropilor.
*pe penultima linie se află coordonatele eroului, iar pe ultima linie se află coordonatele comorii.
 
== Date de iesire ==
 
Fișierul de ieșire turn.out va conține numărul minim de pași pe care îl poate face Susan pentru a ajunge la comoara sa.
 
== Restricții și precizări ==
 
* ≤ n ≤ 100
*1 ≤ z ≤ 30000
*1 ≤ s1 ≤ s2 ≤ 200
*1 ≤ g ≤ 10000
*Se garantează că există soluție pentru toate datele de test.
*Poziția inițială se consideră a fi situată la pasul 1.
*Trapa generează o cădere a eroului pe verticală, până când ajunge într-o cameră fără trapă.
 
== Exemplul 1 ==
 
;turnin.txt
 
:3
 
:9 3 3 3
 
:1 1 3
 
:1 2 1
 
:1 3 2
 
:2 1 1
 
:2 1 3
 
:2 2 2
 
:3 1 1
 
:3 2 3
 
:3 3 3
 
:1 2 3
 
:2 3 2
 
:2 1 2
 
:2 2 3


:3 3 2
* pe prima linie numărul <code>n</code>, reprezentând lungimea laturii turnului.
* pe a doua linie se află numărul <code>z</code>, reprezentând numărul de ziduri, numărul <code>s1</code>, reprezentând numărul de scări descendente, numărul <code>s2</code>, reprezentând numărul de scări descendente și numărul <code>g</code>, reprezentând numărul de gropi.
* pe următoarele <code>z</code> linii se află coordonatele zidurilor.
* pe următoarele <code>s1</code> linii se află coordonatele scărilor ascendente.
* pe următoarele <code>s2</code> linii se află coordonatele scărilor descendente.
* pe următoarele <code>g</code> linii se află coordonatele gropilor.
* pe penultima linie se află coordonatele eroului, iar pe ultima linie se află coordonatele comorii.


:3 1 2
= Date de ieșire =
Fișierul de ieșire <code>turnOUT.txt</code> va conține numărul minim de pași pe care îl poate face Susan pentru a ajunge la comoara sa. În cazul în care restricțiile nu sunt îndeplinite, se va afișa mesajul "Datele nu corespund restrictiilor impuse".


:3 3 1
= Restricții și precizări =


:3 2 1
* <code>1 ≤ n ≤ 100</code>
* <code>1 ≤ z ≤ 30000</code>
* <code>1 ≤ s1 ≤ s2 ≤ 200</code>
* <code>1 ≤ g ≤ 10000</code>
* Se garantează că există soluție pentru toate datele de test.
* Poziția inițială se consideră a fi situată la pasul 1.
* Trapa generează o cădere a eroului pe verticală, până când ajunge într-o cameră fără trapă.


:2 3 1
= Exemplul 1: =
<code>turnIN.txt</code>
3
9 3 3 3
1 1 3
1 2 1
1 3 2
2 1 1
2 1 3
2 2 2
3 1 1
3 2 3
3 3 3
1 2 3
2 3 2
2 1 2
2 2 3
3 3 2
3 1 2
3 3 1
3 2 1
2 3 1
1 1 1
2 2 1
<code>turnOUT.txt</code>
11


:1 1 1
== Explicație ==
Turnul are <code>3</code> etaje. Susan pleacă din celula de coordonate <code>(1 1 1)</code>, iar celula în care se află comoara are coordonatele <code>(2 2 1)</code>. Există <code>9</code> celule în care se află ziduri, <code>3</code> celule în care se află scări ascendente, <code>3</code> celule în care se află scări descendente și <code>3</code> celule în care se află gropi. Traseul cel mai scurt trece prin <code>11</code> camere: <code>(1 1 1) (1 1 2) (1 2 2) (1 2 3) (2 2 3) (2 3 3) (2 3 2) (3 3 2) (3 2 2) (3 2 1) (2 2 1)</code>.


:2 2 1
== Exemplul 2: ==
 
<code>turnIN.txt</code>
;turnout.txt
101
 
9 3 3 3
:Datele introduse corespund restrictiilor impuse.
1 1 3
 
1 2 1
:11
1 3 2
 
<code>turnOUT.txt</code>
== Exemplul 2 ==
Datele nu corespund restrictiilor impuse
 
:
;trunin.txt
 
:0
 
:10 22 32 16
 
:-1 -2 -3
 
:-3 -1 -2
 
:0 0 0
 
:-2 -3 -1
 
:-1 -2 -1
 
:-3 -2 -2
 
:-2 -2 -2
 
:-3 -2 -1
 
:-1 -2 -2
 
:-3 -3 -1
 
:-3 -2 -3
 
:-2 -3 -1
 
:-1 -1 -1
 
:-2 -2 -1
 
:-1 -3 -2
 
:-3 -3 -2
 
;turnout.txt
 
:Datele de intrare nu corespund restrictiilor impuse.


== Rezolvare ==
== Rezolvare ==


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


def distanta_minima(latura_turn, coordonate_camere, coordonate_comoara):
dy = [1, -1, 0, 0]
    n = latura_turn
dz = [0, 0, 1, -1]
    turn = [[0] * n for _ in range(n)]
 
    for coord in coordonate_camere:
        x, y = coord
        turn[x][y] = 1 # Camera blocată
 
    sx, sy = coordonate_comoara[0]
    ex, ey = coordonate_comoara[1]
 
    # Coordonatele deplasării posibile
    deplasare = [(0, 1), (0, -1), (1, 0), (-1, 0)]
 
    # Coordonatele camerelor accesibile
    camere_accesibile = set()
 
    # Construim graful turnului
    for i in range(n):
        for j in range(n):
            if turn[i][j] == 0:
                camere_accesibile.add((i, j))


    # Funcția de verificare a validității unei camere
def inmat(i, j, k, n):
    def este_valida(x, y):
    return 1 <= i <= n and 1 <= j <= n and 1 <= k <= n
        return 0 <= x < n and 0 <= y < n and (x, y) in camere_accesibile


    # Algoritmul BFS pentru a găsi distanța minimă
def lee(n, a, is_, js, ks, ifi, jfi, kfi):
     def bfs(start, scop):
     b = [[[0 for _ in range(n + 1)] for _ in range(n + 1)] for _ in range(n + 1)]
        queue = deque([(start, 0)]) # Coada pentru BFS
    q = deque([(is_, js, ks)])
        vizitat = set([start])  # Set pentru a urmări camerele vizitate
    b[is_][js][ks] = 1


         while queue:
    while q:
             (x, y), pasi = queue.popleft()
        x, y, w = q.popleft()
        if a[x][y][w] != 4:
            for d in range(4):
                ii = x
                jj = y + dy[d]
                kk = w + dz[d]
                if inmat(ii, jj, kk, n) and a[ii][jj][kk] != 1 and b[ii][jj][kk] == 0:
                    b[ii][jj][kk] = b[x][y][w] + 1
                    q.append((ii, jj, kk))
         if a[x][y][w] == 4:
            ii = x
            cnt = 0
            while a[ii][y][w] == 4:
                ii -= 1
                cnt += 1
             if inmat(ii, y, w, n) and a[ii][y][w] != 1 and b[ii][y][w] == 0:
                b[ii][y][w] = b[x][y][w] + cnt
                q.append((ii, y, w))
        elif a[x][y][w] == 3:
            ii = x - 1
            if inmat(ii, y, w, n) and a[ii][y][w] != 1 and b[ii][y][w] == 0:
                b[ii][y][w] = b[x][y][w] + 1
                q.append((ii, y, w))
        elif a[x][y][w] == 2:
            ii = x + 1
            if inmat(ii, y, w, n) and a[ii][y][w] != 1 and b[ii][y][w] == 0:
                b[ii][y][w] = b[x][y][w] + 1
                q.append((ii, y, w))


            if (x, y) == scop:
    return b[ifi][jfi][kfi]
                return pasi  # Am ajuns la comoară


            for dx, dy in deplasare:
def verificare_restrictii(n, z, sa, sd, g):
                nx, ny = x + dx, y + dy
    if not (1 <= n <= 100 and 1 <= z <= 30000 and 1 <= sa <= sd <= 200 and 1 <= g <= 10000):
        with open("turnOUT.txt", "w") as f:
            f.write("Datele nu corespund restrictiilor impuse")
        return False
    return True


                if este_valida(nx, ny) and (nx, ny) not in vizitat:
with open("turnIN.txt", "r") as f:
                    queue.append(((nx, ny), pasi + 1))
    n = int(f.readline().strip())
                    vizitat.add((nx, ny))
    z, sa, sd, g = map(int, f.readline().split())
    if not verificare_restrictii(n, z, sa, sd, g):
        exit()


         return -1 # Comoara nu poate fi atinsă
    a = [[[0 for _ in range(n + 1)] for _ in range(n + 1)] for _ in range(n + 1)]
    for _ in range(z):
         x, y, w = map(int, f.readline().split())
        a[x][y][w] = 1
    for _ in range(sa):
        x, y, w = map(int, f.readline().split())
        a[x][y][w] = 2
    for _ in range(sd):
        x, y, w = map(int, f.readline().split())
        a[x][y][w] = 3
    for _ in range(g):
        x, y, w = map(int, f.readline().split())
        a[x][y][w] = 4
    is_, js, ks = map(int, f.readline().split())
    ifi, jfi, kfi = map(int, f.readline().split())


    rezultat = bfs((sx, sy), (ex, ey))
result = lee(n, a, is_, js, ks, ifi, jfi, kfi)
    return rezultat


rezultat = distanta_minima(latura_turn, camere_blocare, coordonate_comoara)
with open("turnOUT.txt", "w") as f:
print(f"Numărul minim de pași necesari: {rezultat}")
    if result is not None:
        f.write(str(result))


</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 07:00, 23 February 2024

Cerinta[edit | edit source]

Eroul nostru Susan se află într-un turn de formă cubică, de latură n. El dorește să ajungă la comoara ascunsă în interiorul turnului. Din fericire, Susan a făcut rost de o hartă care îi indică cu exactitate coordonatele locului în care se află comoara din turn. Eroul nostru vrea să știe care este distanța minimă pe care o poate parcurge pentru a ajunge la comoară.

Turnul este împărțit în n etaje, iar fiecare etaj este împărțit în n x n celule (camere). O cameră poate:

  • fi blocată, astfel fiind inaccesibilă eroului nostru
  • fi accesibilă, astfel eroul nostru poate intra în aceasta
  • conține o scară ascendentă care îl poate duce pe erou cu un etaj mai sus, în camera situată deasupra camerei curente
  • conține o scară descendentă care îl poate duce pe erou cu un etaj mai jos, în camera situată sub camera curentă
  • conține o trapă prin care eroul va cădea la etajul inferior, în camerele situate sub camera curentă (dacă eroul, în urma căderii, se află într-o cameră ce conține o trapă, el va continua să cadă până se va afla într-o o cameră fără trapă, pe aceeași coloană)

La fiecare trecere dintr-o cameră în alta, eroul execută un pas.

Fiind date latura turnului și coordonatele zidurilor, scărilor, gropilor, eroului și a comorii, se cere să se afișeze numărul minim de pași pe care îl poate parcurge Susan pentru a ajunge la comoară.

Date de intrare[edit | edit source]

Fișierul de intrare turnIN.txt conține:

  • pe prima linie numărul n, reprezentând lungimea laturii turnului.
  • pe a doua linie se află numărul z, reprezentând numărul de ziduri, numărul s1, reprezentând numărul de scări descendente, numărul s2, reprezentând numărul de scări descendente și numărul g, reprezentând numărul de gropi.
  • pe următoarele z linii se află coordonatele zidurilor.
  • pe următoarele s1 linii se află coordonatele scărilor ascendente.
  • pe următoarele s2 linii se află coordonatele scărilor descendente.
  • pe următoarele g linii se află coordonatele gropilor.
  • pe penultima linie se află coordonatele eroului, iar pe ultima linie se află coordonatele comorii.

Date de ieșire[edit | edit source]

Fișierul de ieșire turnOUT.txt va conține numărul minim de pași pe care îl poate face Susan pentru a ajunge la comoara sa. Î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
  • 1 ≤ z ≤ 30000
  • 1 ≤ s1 ≤ s2 ≤ 200
  • 1 ≤ g ≤ 10000
  • Se garantează că există soluție pentru toate datele de test.
  • Poziția inițială se consideră a fi situată la pasul 1.
  • Trapa generează o cădere a eroului pe verticală, până când ajunge într-o cameră fără trapă.

Exemplul 1:[edit | edit source]

turnIN.txt

3
9 3 3 3
1 1 3
1 2 1
1 3 2
2 1 1
2 1 3
2 2 2
3 1 1
3 2 3
3 3 3
1 2 3
2 3 2
2 1 2
2 2 3
3 3 2
3 1 2
3 3 1
3 2 1
2 3 1
1 1 1
2 2 1

turnOUT.txt

11

Explicație[edit | edit source]

Turnul are 3 etaje. Susan pleacă din celula de coordonate (1 1 1), iar celula în care se află comoara are coordonatele (2 2 1). Există 9 celule în care se află ziduri, 3 celule în care se află scări ascendente, 3 celule în care se află scări descendente și 3 celule în care se află gropi. Traseul cel mai scurt trece prin 11 camere: (1 1 1) (1 1 2) (1 2 2) (1 2 3) (2 2 3) (2 3 3) (2 3 2) (3 3 2) (3 2 2) (3 2 1) (2 2 1).

Exemplul 2:[edit | edit source]

turnIN.txt

101
9 3 3 3
1 1 3
1 2 1
1 3 2

turnOUT.txt

Datele nu corespund restrictiilor impuse

Rezolvare[edit | edit source]

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

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

def inmat(i, j, k, n):

   return 1 <= i <= n and 1 <= j <= n and 1 <= k <= n

def lee(n, a, is_, js, ks, ifi, jfi, kfi):

   b = [[[0 for _ in range(n + 1)] for _ in range(n + 1)] for _ in range(n + 1)]
   q = deque([(is_, js, ks)])
   b[is_][js][ks] = 1
   while q:
       x, y, w = q.popleft()
       if a[x][y][w] != 4:
           for d in range(4):
               ii = x
               jj = y + dy[d]
               kk = w + dz[d]
               if inmat(ii, jj, kk, n) and a[ii][jj][kk] != 1 and b[ii][jj][kk] == 0:
                   b[ii][jj][kk] = b[x][y][w] + 1
                   q.append((ii, jj, kk))
       if a[x][y][w] == 4:
           ii = x
           cnt = 0
           while a[ii][y][w] == 4:
               ii -= 1
               cnt += 1
           if inmat(ii, y, w, n) and a[ii][y][w] != 1 and b[ii][y][w] == 0:
               b[ii][y][w] = b[x][y][w] + cnt
               q.append((ii, y, w))
       elif a[x][y][w] == 3:
           ii = x - 1
           if inmat(ii, y, w, n) and a[ii][y][w] != 1 and b[ii][y][w] == 0:
               b[ii][y][w] = b[x][y][w] + 1
               q.append((ii, y, w))
       elif a[x][y][w] == 2:
           ii = x + 1
           if inmat(ii, y, w, n) and a[ii][y][w] != 1 and b[ii][y][w] == 0:
               b[ii][y][w] = b[x][y][w] + 1
               q.append((ii, y, w))
   return b[ifi][jfi][kfi]

def verificare_restrictii(n, z, sa, sd, g):

   if not (1 <= n <= 100 and 1 <= z <= 30000 and 1 <= sa <= sd <= 200 and 1 <= g <= 10000):
       with open("turnOUT.txt", "w") as f:
           f.write("Datele nu corespund restrictiilor impuse")
       return False
   return True

with open("turnIN.txt", "r") as f:

   n = int(f.readline().strip())
   z, sa, sd, g = map(int, f.readline().split())
   if not verificare_restrictii(n, z, sa, sd, g):
       exit()
   a = [[[0 for _ in range(n + 1)] for _ in range(n + 1)] for _ in range(n + 1)]
   for _ in range(z):
       x, y, w = map(int, f.readline().split())
       a[x][y][w] = 1
   for _ in range(sa):
       x, y, w = map(int, f.readline().split())
       a[x][y][w] = 2
   for _ in range(sd):
       x, y, w = map(int, f.readline().split())
       a[x][y][w] = 3
   for _ in range(g):
       x, y, w = map(int, f.readline().split())
       a[x][y][w] = 4
   is_, js, ks = map(int, f.readline().split())
   ifi, jfi, kfi = map(int, f.readline().split())

result = lee(n, a, is_, js, ks, ifi, jfi, kfi)

with open("turnOUT.txt", "w") as f:

   if result is not None:
       f.write(str(result))

</syntaxhighlight>