2724 - LSQ

From Bitnami MediaWiki
Revision as of 08:00, 28 April 2023 by Cata (talk | contribs)

Cerința

Se dă o matrice binară (valori 0 și 1). Să se determine care este latura maximă a unui pătrat cu proprietatea că acesta are pe marginea sa doar valori 1.

Date de intrare

Fișierul de intrare lsq.in conține pe prima linie numerele N și M, reprezentând numărul de linii și numărul de coloane ale matricei, apoi N linii, pe fiecare câte M valori 0 sau 1, neseparate prin niciun spațiu, reprezentând elementele matricei..

Date de ieșire

Fișierul de ieșire lsq.out va conține pe prima linie numărul L, reprezentând lungimea maximă a laturii unui pătrat ce conține doar 1 pe marginea sa.

Restricții și precizări

  • 1 ⩽ N, M ⩽ 1000
  • Se consideră pătrat și cel de latură 1 (conține doar un element).

Exemplu

lsq.in
7 7
0000000
0111100
0101111
0100101
0111111
0000011
0000011
lsq.out
4
Consola
Valid input

Explicație

0 0 0 0 0 0 0
0 1 1 1 1 0 0
0 1 0 1 1 1 1
0 1 0 0 1 0 1
0 1 1 1 1 1 1
0 0 0 0 0 1 1
0 0 0 0 0 1 1

Rezolvare

<syntaxhighlight lang="python"> Nmax = 1005


def compute_matrices(N, M, A):

   LDL = [[0] * M for _ in range(N)]
   CDL = [[0] * M for _ in range(N)]
   LRU = [[0] * M for _ in range(N)]
   CRU = [[0] * M for _ in range(N)]
   for i in range(N):
       for j in range(M):
           if A[i][j] == 1:
               LDL[i][j] = 1 + LDL[i][j - 1] if j > 0 else 1
               CDL[i][j] = 1 + CDL[i - 1][j] if i > 0 else 1
   for i in range(N - 1, -1, -1):
       for j in range(M - 1, -1, -1):
           if A[i][j] == 1:
               LRU[i][j] = 1 + LRU[i][j + 1] if j < M - 1 else 1
               CRU[i][j] = 1 + CRU[i + 1][j] if i < N - 1 else 1
   return LDL, CDL, LRU, CRU


def find_largest_square(N, M, A):

   LDL, CDL, LRU, CRU = compute_matrices(N, M, A)
   ans = 0
   for i in range(N):
       for j in range(M):
           for L in range(min(LDL[i][j], CDL[i][j]), ans, -1):
               if L <= min(LRU[i - L + 1][j - L + 1], CRU[i - L + 1][j - L + 1]):
                   ans = L
                   break
   return ans

def validate_input(n: int, m: int) -> bool:

   return 1 <= n <= 1000 and 1 <= m <= 1000

def main():

   with open("lsq.in", "r") as fin, open("lsq.out", "w") as fout:
       N, M = map(int, fin.readline().split())
       A = [list(map(int, fin.readline().strip())) for _ in range(N)]
       if not validate_input(N, M):
           print("Invalid input!")
           return
       else:
           print("Valid input")
       ans = find_largest_square(N, M, A)
       fout.write(str(ans) + "\n")


if __name__ == "__main__":

   main()

</syntaxhighlight>

Explicație cod

Acesta este un program Python care calculează dimensiunea celui mai mare pătrat complet format din cifrele de 1 dintr-o matrice dată. Matricea este dată ca o listă de liste de cifre. Algoritmul folosit pentru a găsi răspunsul constă în calcularea a patru matrice auxiliare, folosind programarea dinamică pentru a calcula lungimea celui mai mare pătrat posibil cu colțul din stânga sus la poziția curentă. Apoi, se parcurge matricea și se caută cel mai mare pătrat complet, verificând dacă toate cele patru laturi au o lungime cel puțin egală cu dimensiunea pătratului. În caz afirmativ, se actualizează dimensiunea maximă a pătratului.

Funcția validate_input() verifică dacă intrarea este validă, adică dacă dimensiunea matricei se află între 1 și 1000 inclusiv. Funcția main() citește matricea din fișierul "lsq.in", validează intrarea și apoi calculează și scrie dimensiunea celui mai mare pătrat complet în fișierul "lsq.out".