3573 - Joc 11

De la Universitas MediaWiki
Versiunea pentru tipărire nu mai este suportată și poate avea erori de randare. Vă rugăm să vă actualizați bookmarkurile browserului și să folosiți funcția implicită de tipărire a browserului.

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

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()