2432 - Cruce

From Bitnami MediaWiki

Se consideră o matrice pătratică de dimensiune N, conţinând numere naturale. Numim cruce de lăţime K reuniunea mulțimii tuturor elementelor aflate pe K linii consecutive ale matricei și a mulțimii tuturor elementelor aflate pe K coloane consecutive ale matricei. Două elemente ale matricei se consideră distincte dacă sunt situate pe poziții distincte în matrice. Se acceptă şi forma degenerată a unei cruci, în formă de T sau L, când una dintre liniile sau coloanele care formează crucea sunt chiar la marginea matricei. Vom defini valoarea unei cruci ca fiind suma elementelor din care aceasta este formată.

Cerința[edit | edit source]

Scrieți un program care, pentru o valoare K dată, determină o cruce de lățime K a cărei valoare este maximă și poziția ei în matrice. Această poziție va fi exprimată prin perechea de indici reprezentând prima linie din cele K consecutive și prima coloană din cele K consecutive din care este formată crucea.

Date de intrare[edit | edit source]

Fişierul cruce.in conţine pe prima linie numerele N şi K, iar pe următoarele N linii câte N numere întregi reprezentând în ordine, pe linii, elementele matricei. Numerele de pe aceeaşi linie sunt separate prin câte un spaţiu.

Date de ieșire[edit | edit source]

Fişierul cruce.out va conţine trei numere Vmax L C, separate prin câte un spaţiu, reprezentând valoarea maximă determinată pentru o cruce de lățime K, respectiv linia și coloana care exprimă poziția acesteia în matrice.

Restricții și precizări[edit | edit source]

  • 1 ≤ N ≤ 500
  • 1 ≤ K < N
  • Numerele din matrice sunt din intervalul [-5000, 5000]
  • Liniile şi coloanele se indexează începând cu 1.
  • Dacă există mai multe cruci de lățime K de valoare maximă, se va lua în considerare poziția cu indicele liniei mai mic, iar în caz de egalitate a liniilor poziția celei cu indicele coloanei mai mic.
  • La olimpiadă s-au oferit 10 puncte din oficiu, aici vor fi date pe exemple.

Exemplu:[edit | edit source]

cruce.in

5 2
1 -2 3 -1 4
-3 2 2 -2 -1
1 2 3 4 5
1 0 -7 1 1
3 2 1 2 3

cruce.out

23 2 4

Explicație[edit | edit source]

Elementele ce formează crucea de valoare maxima sunt:

1 -2 3 -1 4

-3 2 2 -2 -1

1 2 3 4 5

1 0 -7 1 1

3 2 1 2 3

<syntaxhighlight lang="python" line="1"> def calculeaza_prefix_sum(matrice, N):

   prefix_sum = [[0] * (N + 1) for _ in range(N + 1)]
   for i in range(1, N + 1):
       for j in range(1, N + 1):
           prefix_sum[i][j] = matrice[i - 1][j - 1] \
                               + prefix_sum[i - 1][j] \
                               + prefix_sum[i][j - 1] \
                               - prefix_sum[i - 1][j - 1]
   return prefix_sum

def suma_submatrice(prefix_sum, x1, y1, x2, y2):

   return (prefix_sum[x2][y2]
           - prefix_sum[x1 - 1][y2]
           - prefix_sum[x2][y1 - 1]
           + prefix_sum[x1 - 1][y1 - 1])

def cruce_maxima(matrice, N, K):

   prefix_sum = calculeaza_prefix_sum(matrice, N)
   max_valoare = -1
   max_pos = (0, 0)
   
   for i in range(1, N - K + 2):
       for j in range(1, N - K + 2):
           # Suma liniilor K consecutive
           suma_linii = 0
           for r in range(K):
               suma_linii += suma_submatrice(prefix_sum, i + r, j, i + r, j + K - 1)
               
           # Suma coloanelor K consecutive
           suma_coloane = 0
           for c in range(K):
               suma_coloane += suma_submatrice(prefix_sum, i, j + c, i + K - 1, j + c)
               
           # Calculul valorii crucii
           suma_cruce = suma_linii + suma_coloane - suma_submatrice(prefix_sum, i, j, i + K - 1, j + K - 1)
           
           if suma_cruce > max_valoare:
               max_valoare = suma_cruce
               max_pos = (i, j)
   
   return max_valoare, max_pos

def main():

   import sys
   input = sys.stdin.read
   data = input().split()
   
   N = int(data[0])
   K = int(data[1])
   matrice = []
   
   index = 2
   for _ in range(N):
       matrice.append([int(x) for x in data[index:index + N]])
       index += N
   
   max_valoare, max_pos = cruce_maxima(matrice, N, K)
   print(max_valoare)
   print(max_pos[0], max_pos[1])

if __name__ == "__main__":

   main()

</syntaxhighlight>