0957 - Zana

De la Universitas MediaWiki

Enunț

Castelul Zânei Spiriduşilor este construit pe o suprafaţă dreptunghiulară având n*m camere identice, de formă pătratică, dispuse câte m pe direcţia Ox şi câte n pe direcţia Oy ca în desenul de mai jos în care n=3 şi m=6. Din fiecare cameră se poate intra în orice cameră învecinată, cameră care are un perete comun cu acesta. Fiecare cameră este identificată prin coordonatele sale, ca în figură.

Zana-enunt-1.png


În castel, trăiesc k spiriduşi împreună cu Zâna lor. Fiind în curând aniversarea zilei de naştere a Zânei, fiecare spiriduş a pregătit câte un cadou pe care îl ascunde, nevăzut de ceilalţi, într-una din camerele castelului. Tradiţia acestei sărbătoriri, impune următoarele reguli:

În căutarea cadourilor, Zâna porneşte din camera de coordonate (1,1). Ea se deplasează prin camerele castelului cât timp în aceste camere nu se află niciun cadou.

Căutarea se încheie în momentul în care Zâna intră într-o cameră în care se află cel puţin un cadou. Zână va primi toate cadourile aflate în acestă cameră, restul cadourilor vor dispărea.

Cerinţă

Scrieţi un program care să citească din fişierul zana.in numerele naturale n, m, k şi cele k coordonatele ale camerelor în care spiriduşii au ascuns cadourile, şi care să determine:

a) numărul n1 maxim de cadouri pe care le poate primi Zâna în urma respectării regulilor;

b) numărului n2 al camerelor în care poate ajunge Zâna respectând regulile, camere ce conţin fiecare câte n1 cadouri.

Date de intrare

Fișierul de intrare zanain.txt conţine pe prima linie cele trei numere naturale: n m k, separate prin câte un spaţiu. Pe fiecare din următoarele k linii, câte una pentru fiecare spiriduş, sunt scrise câte două numere naturale: i j, separate printr-un spaţiu, reprezentând coordonatele camerei în care spiriduşul curent a ascuns cadoul.

Date de ieșire

Fișierul de ieșire zanaout.txt va conține două linii. Pe prima linie se va scrie numărul natural n1 reprezentând numărul maxim de cadouri pe care le poate primi Zâna. Pe cea de-a doua linie se va scrie numărul natural n2, reprezentând numărul camerelor în care poate ajunge Zâna şi care conţin fiecare câte n1 cadouri.

Restricții și precizări

  • 1 ≤ n ≤ 180, 1 ≤ m ≤ 180, 1 ≤ k ≤ 30.000
  • 1 ≤ i ≤ n, 1 ≤ j ≤ m
  • toate valorile din fișierul de intrare sunt numere naturale

Exemplu:

zanain.txt

3 5 11

1 5

1 5

1 3

1 3

1 4

1 4

1 4

2 4

2 4

2 5

3 2

zanaout.txt

2

2

Explicație

Castelul are 3*5=15 camere. Coordonatele acestora sunt cele din figura 1, iar cadourile sunt dispuse ca în figura următoare:

Zana-enunt-2 (1).png


Zâna porneşte căutarea începând din camera de coordonate (1,1). Camera cu număr maxim de cadouri (3) are coordonatele (1,4), dar zâna nu poate ajunge în acestă cameră, deoarece pentru a ajunge în acesta ea trebuie să treacă prin una din camerele de coordonate (1,3), (2,4), (2,5) în care se află cadouri. Conform regulamentului, căutarea se va încheia în una din aceste camere. Astfel zâna poate parcurge camerele (1,1), (1,2), (1,3) sau (1,1), (1,2), (2,2), (2,3), (2,4), etc pentru a ajunge într-una din cele n2=2 camere cu număr n1=2 maxim de cadouri.

Rezolvare

def este_input_valid(n, m, k, i, j):
    return (1 <= n <= 180 and 1 <= m <= 180 and 1 <= k <= 30000 and
            1 <= i <= n and 1 <= j <= m)
def fill(i, j):
    b[i][j] = 1
    a[i][j] = -1
    if a[i + 1][j] == 0 and i + 1 <= n:
        fill(i + 1, j)
    if a[i - 1][j] == 0 and i - 1 >= 1:
        fill(i - 1, j)
    if a[i][j + 1] == 0 and j + 1 <= m:
        fill(i, j + 1)
    if a[i][j - 1] == 0 and j - 1 >= 1:
        fill(i, j - 1)


with open("zanain.txt", "r") as f_in, open("zanaout.txt", "w") as f_out:
    n, m, k = map(int, f_in.readline().split())
    a = [[0] * 101 for _ in range(101)]
    b = [[0] * 101 for _ in range(101)]

    for _ in range(k):
        x, y = map(int, f_in.readline().split())
        a[x][y] += 1

    fill(1, 1)

    max_val, cnt = 0, 0

    for i in range(1, n + 1):
        for j in range(1, m + 1):
            if a[i][j] > 0 and (b[i + 1][j] == 1 or b[i - 1][j] == 1 or b[i][j + 1] == 1 or b[i][j - 1] == 1):
                if a[i][j] > max_val:
                    max_val = a[i][j]
                    cnt = 0
                if a[i][j] == max_val:
                    cnt += 1

    f_out.write(str(max_val) + '\n' + str(cnt) + '\n')

if __name__ == "__main__":
    fill(i,j)