2390 - rj

De la Universitas MediaWiki

Enunt

În ultima ecranizare a celebrei piese shakespeariene Romeo și Julieta trăiesc într-un oraș modern, comunică prin e-mail și chiar învață să programeze. Într-o secvență tulburătoare sunt prezentate frământările interioare ale celor doi eroi încercând fără succes să scrie un program care să determine un punct optim de întâlnire.

Ei au analizat harta orașului și au reprezentat-o sub forma unei matrice cu N linii şi M coloane, în matrice fiind marcate cu spațiu zonele prin care se poate trece (străzi lipsite de pericole) şi cu X zonele prin care nu se poate trece. De asemenea, în matrice au marcat cu R locul în care se află locuința lui Romeo, iar cu J locul în care se află locuința Julietei. Ei se pot deplasa numai prin zonele care sunt marcate cu spaţiu, din poziţia curentă în oricare dintre cele 8 poziţii învecinate (pe orizontală, verticală sau diagonale).

Cum lui Romeo nu îi place să aştepte şi nici să se lase aşteptat n-ar fi tocmai bine, ei au hotărât că trebuie să aleagă un punct de întâlnire în care atât Romeo, cât şi Julieta să poată ajunge în acelaşi timp, plecând de acasă. Fiindcă la întâlniri amândoi vin într-un suflet, ei estimează timpul necesar pentru a ajunge la întâlnire prin numărul de elemente din matrice care constituie drumul cel mai scurt de acasă până la punctul de întâlnire. Şi cum probabil există mai multe puncte de întâlnire posibile, ei vor să îl aleagă pe cel în care timpul necesar pentru a ajunge la punctul de întâlnire este minim.

Cerinta

Scrieţi un program care să determine o poziţie pe hartă la care Romeo şi Julieta pot să ajungă în acelaşi timp. Dacă există mai multe soluţii, programul trebuie să determine o soluţie pentru care timpul este minim.

Date de intrare

Fișierul de intrare rj.in conține pe prima linie numerele naturale N M, care reprezintă numărul de linii şi respectiv de coloane ale matricei, separate prin spațiu, iar pe fiecare dintre următoarele N linii se află M caractere (care pot fi doar R, J, X sau spațiu) reprezentând matricea.

Date de iesire

Fișierul de ieșire rj.out va conține o singură linie pe care sunt scrise trei numere naturale separate prin câte un spaţiu tmin x y, având semnificaţia: x y reprezinţă punctul de întâlnire (x – numărul liniei, y – numărul coloanei); tmin este timpul minim în care Romeo (respectiv Julieta) ajunge la punctul de întâlnire.

Restricții și precizări

  • 1 < N, M < 101
  • Liniile şi coloanele matricei sunt numerotate începând cu 1.
  • Pentru datele de test există întotdeauna soluţie.

Exemplul 1

rjin.txt
5 8
XXR XXX
X X X
J X X X
XX
XXX XXXX
rjout.txt
Datele introduse corespund restrictiilor impuse.
4 4 4

Exemplul 2

rjin.txt
0 4
RXX RRR
F F F
K L L L
V V
OOO TTRR
rjout.txt
Datele de intrare nu corespund restrictiilor impuse.

Rezolvare

from collections import deque

def este_valid(x, y, N, M):
    return 0 <= x < N and 0 <= y < M

def bfs(matrice, start):
    N, M = len(matrice), len(matrice[0])
    vizitat = [[False] * M for _ in range(N)]
    timp = [[float('inf')] * M for _ in range(N)]
    
    x, y = start
    queue = deque([(x, y, 0)])
    vizitat[x][y] = True
    timp[x][y] = 0

    deplasare = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (-1, 1), (1, -1), (1, 1)]

    while queue:
        x, y, t = queue.popleft()

        for dx, dy in deplasare:
            nx, ny = x + dx, y + dy

            if este_valid(nx, ny, N, M) and not vizitat[nx][ny] and matrice[nx][ny] == ' ':
                queue.append((nx, ny, t + 1))
                vizitat[nx][ny] = True
                timp[nx][ny] = t + 1

    return timp

def alege_punct_intalnire(romeo, julieta, N, M):
    matrice = [
        [' ', ' ', ' ', ' ', ' ', ' ', ' '],
        [' ', 'X', ' ', ' ', ' ', 'X', ' '],
        [' ', ' ', ' ', ' ', ' ', ' ', ' '],
        [' ', ' ', 'X', ' ', ' ', ' ', ' '],
        [' ', ' ', ' ', ' ', ' ', ' ', ' '],
        [' ', ' ', ' ', ' ', ' ', ' ', ' '],
        [' ', 'X', ' ', ' ', ' ', 'X', ' '],
    ]

    timp_romeo = bfs(matrice, romeo)
    timp_julieta = bfs(matrice, julieta)

    min_timp_total = float('inf')
    punct_intalnire = None

    for i in range(N):
        for j in range(M):
            timp_total = timp_romeo[i][j] + timp_julieta[i][j]
            if timp_total < min_timp_total:
                min_timp_total = timp_total
                punct_intalnire = (i, j)

    return punct_intalnire

print(f"Punctul de întâlnire este: {punct_intalnire}")