3573 - Joc 11

From Bitnami MediaWiki

Enunt

Pentru un concurs de design de jocuri, Gigel vrea să construiască un joc. La joc participă n concurenţi numerotaţi de la 1 la n. Fiecare concurent are la dispoziţie câte un şir de m încăperi, numerotate de la 1 la m. Scopul jocului este de a găsi o comoară ascunsă în una din aceste încăperi. Fiecare încăpere conţine un cod, număr natural, fie egal cu 0, fie având cel puţin 2 cifre. Ultima cifră indică numărul de etape de penalizare, adică numărul de etape în care concurentul nu are voie să părăsească încăperea. Numărul obţinut prin eliminarea ultimei cifre a codului indică numărul încăperii în care se va deplasa acesta la următoarea etapă sau la expirarea penalizării.

Există două excepţii de la regula de definire a codului: numărul 9999 codifică o încăpere conţinând o comoară, iar numărul 0 o încăpere conţinând o capcana.

În etapa 1 fiecare jucător intră în încăperea 1 din şirul său de încăperi. În funcţie de codul găsit în încăpere sunt posibile următoarele situaţii:

  • codul găsit este 9999 ceea ce înseamnă că jucătorul este câştigător şi jocul se încheie la finalul acestei etape;
  • codul găsit este 0 ceea ce duce la eliminarea sa din joc;
  • pentru celelalte coduri, după efectuarea etapelor de penalizare, jucătorul efectuează o deplasare în încăperea indicată de cod. De exemplu la întâlnirea codul 157, după efectuarea celor 7 etape de penalizare jucătorul se va deplasa în camera 15.

Trecerea de la o etapă la alta se realizează simultan pentru toţi concurenţii.

Cerinţa

Fiind dat numărul n de concurenţi, numărul m de încăperi alocate fiecărui concurent, şi codurile din cele n×m încăperi să se determine câştigătorul jocului, numărul încăperii în care a găsit comoara, numărul de etape parcurse până când câştigătorul găseşte comoara precum şi numărul de concurenţi eliminaţi din joc până la etapa respectivă (inclusiv).

Date de intrare

Prima linie a fişierului de intrare joc11.in conţine două numere naturale n şi m, separate printr-un spaţiu, reprezentând numărul concurenţilor, respectiv numărul încăperilor. Următoarele n linii conţin câte m numere naturale, separate prin câte un spaţiu, reprezentând codurile din fiecare încăpere.

Date de ieșire

Prima linie a fişierului de ieşire joc11.out va conţine patru numere naturale separate prin câte un spaţiu, reprezentând indicele câştigătorului, numărul încăperii unde a găsit comoara, numărul etapei în care a câştigat şi respectiv numărul de concurenţi eliminaţi din joc.

Restricţii şi precizări

  • 1 ≤ n ≤ 400
  • 1 ≤ m ≤ 900
  • Pentru toate testele de intrare se garantează că există exact un câştigător.

Exemplu

joc11.in
4 8
0 9999 41 50 61 70 80 30
30 80 60 60 9999 21 40 50
20 30 40 50 61 71 81 9999
20 30 50 0 61 71 9999 41
joc11.out
2 5 7 1


Explicație

Câştigă jucătorul al 2-lea, după 7 etape, iar încăperea în care a găsit comoara este încăperea 5. În cele 7 etape a fost eliminat un singur concurent şi anume primul concurent. Încăperile prin care trece jucătorul câştigător până la final sunt: 1->3->6->2->8->5

Rezolvare

<syntaxhighlight lang="python" line> def simulate_game(n, m, rooms):

   winner = None
   room_number = None
   steps = 0
   eliminated = 0
   # Cream o listă de seturi pentru a memora concurenții eliminați în fiecare etapă
   eliminated_each_step = [set() for _ in range(m)]
   for step in range(m):
       next_rooms = [0] * n  # Inițializăm lista cu următoarele încăperi pentru fiecare concurent
       for i in range(n):
           if i in eliminated_each_step[step]:
               continue  # Dacă concurentul este deja eliminat în această etapă, nu facem nimic cu el
           code = rooms[i][step]  # Codul din încăperea curentă a concurentului
           if code == 9999:
               winner = i + 1
               room_number = step + 1
               steps = step + 1
               return winner, room_number, steps, eliminated
           if code == 0:
               eliminated += 1
               eliminated_each_step[step].add(i)
           else:
               next_room = int(str(code)[:-1])  # Obținem numărul următoarei încăperi
               next_rooms[next_room - 1] += 1
       # Actualizăm seturile de concurenți eliminați pentru etapele următoare
       for i in range(n):
           if next_rooms[i] > 1:
               eliminated_each_step[step + 1].add(i)
   return winner, room_number, steps, eliminated

def main():

   with open("joc11.in", "r") as fin:
       n, m = map(int, fin.readline().split())
       rooms = [list(map(int, fin.readline().split())) for _ in range(n)]
   winner, room_number, steps, eliminated = simulate_game(n, m, rooms)
   with open("joc11.out", "w") as fout:
       fout.write(f"{winner} {room_number} {steps} {eliminated}\n")

if __name__ == "__main__":

   main()

</syntaxhighlight>