Python

Заполните матрицу, содержащую N строк и M столбцов, натуральными числами змейкой, как на рисунке:

BS
Boris Sumin
117
Не особо сложно заполнять змейкой этой.

Функциональный алгоритм (ну, почти):
 def printMatrix(matrix):
print(*(" ".join(map(lambda i: "%3d" % i, row)) for row in matrix), sep = '\n')

N, M = map(int, input("Размерность матрицы через пробел: ").split())
D = N + M - 1 # кол-во диагоналей
mnn, mxn = (N, M) if N < M else (M, N)
matrix = [[0] * M for _ in range(N)]

def diagLen(d): # длина диагонали с номером d
return d + 1 if d < mnn else mnn if d < mxn else D - d

def diagLensUpTo(d): # сумма длин диагоналей с номерами от 0 до d, не включая d
prog = min(d, mnn - 1) # кол-во возрастающих диагоналей
const = min(mxn, d) - prog # кол-во константных диагоналей
reg = max(d - prog - const, 0) # кол-во убывающих диагоналей
return prog * (prog + 1) // 2 + const * mnn + (mnn * (mnn - 1) - (mnn - 1 - reg) * (mnn - reg)) // 2

def snakeElem(i, j):
d = i + j # номер диагонали
vad = 0 if d < N else N - d - 1 # вертикальная поправка
return diagLensUpTo(d) + (j + 1 + vad if d % 2 else diagLen(d) - j - vad)

printMatrix([[snakeElem(i, j) for j in range(M)] for i in range(N)])
Значение каждого элемента вычисляется на основе его индексов и суммы длин предыдущих диагоналей. Используется такое понятие, как номер диагонали (это сумма индексов). Номер диагонали, длина диагонали и сумма предшествующих длин рассчитываются за константное время, а общая сложность алгоритма - линейная (O(N * M)). Матрица заполняется пробегом по строкам и элементам каждой строки, причём, порядок заполнения не влияет на результат.

Императивный алгоритм:
 def printMatrix(matrix):
print(*(" ".join(map(lambda i: "%3d" % i, row)) for row in matrix), sep = '\n')

N, M = map(int, input("Размерность матрицы через пробел: ").split())
D = N + M - 1 # кол-во диагоналей
mnn, mxn = (N, M) if N < M else (M, N)
matrix = [[0] * M for _ in range(N)]

def diagLen(d): # длина диагонали с номером d
return d + 1 if d < mnn else mnn if d < mxn else D - d

seq = 1
for d in range(D): # цикл по диагоналям
dl = diagLen(d)
vad = 0 if d < N else N - d - 1 # вертикальная поправка
for j in range(dl): # цикл по элементам диагонали
matrix[d - j + vad][j - vad] = seq + (j if d % 2 else dl - j - 1)
seq += dl

printMatrix(matrix)
В императивной версии матрица заполняется по диагоналям (i - счётчик диагоналей с 0, j - индекс элемента внутри диагонали). Нечётные диагонали заполняются в прямом порядке, чётные - в обратном. Используется сквозной счётчик (seq), из-за чего алгоритм жёстко привязан к порядку итерирования, и распараллелить его в случае чего не получится. Сложность - та же, что у функциональной версии (O(N * M)).

Примеры:
 1   3   4
2 5 8
6 7 9

1 3 4 9
2 5 8 10
6 7 11 12

1 3 4 10 11 18 19 26 27 34 35 42 43 50 51 58 59 66 67 74
2 5 9 12 17 20 25 28 33 36 41 44 49 52 57 60 65 68 73 75
6 8 13 16 21 24 29 32 37 40 45 48 53 56 61 64 69 72 76 79
7 14 15 22 23 30 31 38 39 46 47 54 55 62 63 70 71 77 78 80

1 3 4 10
2 5 9 11
6 8 12 17
7 13 16 18
14 15 19 20
SB
Slawa63 Bolcshakow
87 571
Лучший ответ
 def zigzag(rows, cols): 
mat = [[0 for col in range(cols)] for row in range(rows)]
row, col = 0, 0
for i in range(1, rows * cols + 1):
mat[row][col] = i
if (row + col) % 2 != 0:
if col == cols - 1:
row += 1
elif row == 0:
col += 1
else:
row -= 1
col += 1
else:
if row == rows - 1:
col += 1
elif col == 0:
row += 1
else:
row += 1
col -= 1
return mat

rows, cols = int(input('N = ')), int(input('M = '))
matrix = zigzag(rows, cols)
for row in matrix:
print(' '.join(f'{n:3}' for n in row))
Или так:
 N, M = int(input('N = ')), int(input('M = ')) 
matrix = [[0 for x in range(M)] for y in range(N)]
compare = lambda xy: (xy[0] + xy[1], -xy[1] if not (xy[0] + xy[1]) % 2 else xy[1])
for n, (x, y) in enumerate(sorted(((x, y) for x in range(N) for y in range(M)), key=compare)):
matrix[x][y] = n+1
for row in matrix:
print(' '.join(f'{n:3}' for n in row))

Похожие вопросы