Комментарии 10
Спасибо.
Интересная задача. Но ИМХО нужно уточнить формулировку:
Матрица уже заполнена нулями или ее нужно инициализировать? Если нужно, то можно не только нулями? (Первым делом приходит идея вычислить элементы гл. диагонали до середины). Можно включить в циклы инициализации вспомогательный вектор с записями (структурами) i,j, где i,j — координаты элемента матрицы?
Интересная задача. Но ИМХО нужно уточнить формулировку:
Итак, задача: разработать алгоритм для вычисления значения элемента спиральной матрицы на основании его координат [i, j] и размера самой матрицы, пользуясь только простыми арифметическими вычислениями. Исключение составляет модуль — абсолютное значение числа.
Матрица уже заполнена нулями или ее нужно инициализировать? Если нужно, то можно не только нулями? (Первым делом приходит идея вычислить элементы гл. диагонали до середины). Можно включить в циклы инициализации вспомогательный вектор с записями (структурами) i,j, где i,j — координаты элемента матрицы?
А матрицу нельзя развернуть, заполнить и закрутить обратно? :)
Формулу можно упростить, если выводить её разворачивая спираль из центра с координатами (0,0) наружу — тогда N в формуле не будет. Чтобы привести её к исходному виду, нужно просто пересчитать координаты для конкретного N, а спираль развернуть вычитанием из максимального значения +1.
Можно попробовать и так, но предполагаю, что код меньше не станет (не пробовал — может кто и выведет покороче код). Если систему координат централизировать, то придется работать с отрицательными значениями — формула(если ее можно так назвать) будет такой же громоздкой. А вычитая из максимального значения, все равно придется использовать N (максимальное значение это — N * N). Ну вообщем как-то так.
Предложу
вариант решения
2 цикла перебирают элементы матрицы, только вложенный порезан на 4 малых цикла для перечисления нужных участков строк и столбцов.program tmp;
{Delpi 7}
{$APPTYPE CONSOLE}
uses
SysUtils,System;
var
M : array of array of integer;
N : integer;
i,j,c : integer;
level, start, fin : integer;
v : integer;
stop: integer;
begin
write ('N=?');
readln (N);
SetLength(M,N+1,N+1);
{
//
for i :=1 to N do
for j:= 1 to N do
M[i,j]:= 0;
//
}
v := 0;
start := 0;
fin := N;
i:= 1;
stop := N * N div 2 + N mod 2;
for level:=1 to stop do // main loop
begin
start := start+1;
for c:=start to fin do // from left to right
begin
v := v+1;
M [i,c] := v;
j := c;
end;
start := start+1;
for c:=start to fin do // from top to bot
begin
v := v+1;
M [c,j] := v;
i := c;
end;
start := start-1;
fin := fin-1;
for c:=fin downto start do // from right to left
begin
v := v+1;
M [i,c] := v;
j := c;
end;
for c:=fin downto start+1 do // from bot to top+1
begin
v := v+1;
M [c,j] := v;
i := c;
end;
end; // main loop
// print result
for i :=1 to N do
begin
for j:= 1 to N do
write (M[i,j]:3);
writeln;
end;
writeln ('v=',v,'=N*N');
write ('Press anykey to exit...');
readln;
end.
Отличное решение, только возможно ли в любой момент на основании координат (i, j) и размера матрицы получить значение любой ячейки? Через функцию.
Очевидно, возможно. Начиная с первого элемента обходить м-цу описанной процедурой, но не до конца (до полоного заполнения м-цы), а до элемента (i, j). Важно, что каждый элемент заполняется нужным значением только однажды, и оно не меняется. Можно оформить, как функцию от (i, j), которая возвратит искомое значение. Если предполагается, что вызовов функции будет много, то лучше обсчитать всю матрицу и просто читать значения нужных элементов.
Да это моя ошибка в условии задачи. Я не заложил там без «внутренних дополнительных циклов», хотя это подразумевалось. Кроме того, также считалось, что циклы сами состоят из условных переходов (условие выхода или входа, причем логически это заложено на «высоком» уровне). Мне следовало это обозначить.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Альтернативный способ заполнения «спиральной матрицы»