Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Задачи _ Задача с двумерным массивом

Автор: Relrin 2.12.2010 0:09

Дан массив A размерности n*m . Получить одномерный массив B, элементы которого получены путем суммирования элементов исходного массива , находящихся по периметрам.

В качестве примера, вот набросал, изображение такого рода:
Прикрепленное изображение

Прогресс не очень далеко, а может и нет. Работает правда этот кусочек кода для массива n*n, а вот для n*m ломаю голову... Пока дошел вот до этого:


k:=n div 2;
for i:=1 to k do begin
sum:=0;
{строки}
for j:=i to n-i+1 do
sum:=sum+x[i,j]+x[n-i+1,j];
{столбцы}
for j:=i+1 to n-i do
sum:=sum+x[j,i]+x[j,n-i+1];
writeln(sum); {вывод суммы}
end;
if n mod 2=1 then
writeln(x[k+1,k+1]);


Автор: Relrin 2.12.2010 0:34

Немного продвинулся вперед, однако, подсчитывает местами неправильно (скажем 3*3 считает правильно, если больше чем 3*3 - то уже неправильные подсчеты)

 
k:=n div 2;
p:=m div 2;
for i:=1 to k do
begin
for d:=1 to p do
begin
sum:=0;
{строки}
for j:=i to n-i+1 do
sum:=sum+a[i,j]+a[m-d+1,j];
{столбцы}
for j:=d+1 to m-i do
sum:=sum+a[j,i]+a[j,n-i+1];
b[count]:=sum;
if count<=i then count:=count+1;
end;
end;

if (n mod 2=1) and (m mod 2=1) and (n=m) then
b[count]:=a[k+1,p+1];


Автор: Krjuger 2.12.2010 0:42

Дам небольшую идею.Вот смотри,если матрица у нас не квадратная,и допустим n>m,то мы получим что строк больше столбцов (логично),но тогда у нас останется поледний центральный столбец,и несколько строк вместо одного центрального элемента,а если m>n,то ситуация получится обратной.Самое логичное разделить да 2 случая.Затем,поразмышляйте,как можно избавится от 2 внутрених циклов внутри for i:=1 to k do begin.Приглядитесь к ним,ведь они отличаются лиш чем?поменялись местами i,j и j вы учеличили на один)

Автор: Relrin 2.12.2010 2:31

UP!

Автор: Lapp 2.12.2010 11:12

Боюсь, что все гораздо проще.. smile.gif
Способ, которым ты пошел, в корне порочен. Нет смысла обходить специальным образом, если все равно нужно просуммировать все. Основная идея - определить минимальное расстояние до края (расстояние до ближайшего края) массива. Это и будет "номер контура".
Вот тебе решение, разбирайся. Если будут вопросы - задавай, отвечу..

  if m<n then d:=(m-1)div 2+1 else d:=(n-1)div 2+1;  // calculating the b size
for i:=1 to m do for j:=1 to n do begin
k:=d; // set to max possible
if i<k then k:=i; // top distance
if j<k then k:=j; // left distance
if m-i+1<k then k:=m-i+1; // bottom distance
if n-j+1<k then k:=n-j+1; // right distance
Inc(b[k],a[i,j]); // adding to sum array
end;

Автор: Lapp 2.12.2010 12:26

Но если ты все же хочешь выяснить, как решить эту задачу обходом по отдельным периметрам (контурам), то вот тебе другое решение. Рекомендую тебе с ним тоже разобраться, поскольку лучше свои ошибки понимать до конца.

  if m<n then d:=(m-1)div 2+1 else d:=(n-1)div 2+1;  // calculate contours amount (size of b)
for i:=1 to d do begin // cycle through contours
for j:=i to m-i+1 do begin // rows (with edges)
Inc(b[i],a[j,i]);
if i<n-i+1 then Inc(b[i],a[j,n-i+1]); // do not count a central row twice
end;
for j:=i+1 to n-i do begin // columns (edges excluded)
Inc(b[i],a[i,j]);
if i<m-i+1 then Inc(b[i],a[m-i+1,j]); // do not count a central column twice
end
end;

Автор: Relrin 2.12.2010 17:40

Цитата(Lapp @ 2.12.2010 9:26) *

Но если ты все же хочешь выяснить, как решить эту задачу обходом по отдельным периметрам (контурам), то вот тебе другое решение. Рекомендую тебе с ним тоже разобраться, поскольку лучше свои ошибки понимать до конца.
  if m<n then d:=(m-1)div 2+1 else d:=(n-1)div 2+1;  // calculate contours amount (size of b)
for i:=1 to d do begin // cycle through contours
for j:=i to m-i+1 do begin // rows (with edges)
Inc(b[i],a[j,i]);
if i<n-i+1 then Inc(b[i],a[j,n-i+1]); // do not count a central row twice
end;
for j:=i+1 to n-i do begin // columns (edges excluded)
Inc(b[i],a[i,j]);
if i<m-i+1 then Inc(b[i],a[m-i+1,j]); // do not count a central column twice
end
end;


Спасибо! Немного уже раскрутил задачу с твоей помощью. Только проблема с подсчетом неквадратной матрицы осталась, т.к. подсчеты неправильные идут уже с первого элемента

Автор: Relrin 2.12.2010 19:48

Проблема в подсчете неквадратной матрицы в том(установлены проверками), что при n<m(пускай будет 3*4) считает 2ой элемент по вертикали, если n>m, то по горизонтали

Автор: Relrin 2.12.2010 20:36

Сейчас пытаюсь приделать условия к циклам. Отдельно считаем периметр если m>n и m<n... Нужна помощь blink.gif


if m<n then d:=(n-1)div 2+1 else d:=(m-1)div 2+1;
for i:=1 to d do begin
sum:=0;
if count<=i then count:=count+1;
{строки}
for j:=i to m-i+1 do
begin
sum:=sum+a[j,i];
if (i<n-i+1) and (m<=n) then sum:=sum+a[j,n-i+1];
if (i<m-i+1) and (m>n) then sum:=sum+a[j,m-i+1];
end;
{столбцы}
for j:=i+1 to n-i do
begin
sum:=sum+a[i,j];
if (i<m-i+1) and (m<=n) then sum:=sum+a[m-i+1,j];
if (i<n-i+1) and (m>n) then sum:=sum+a[n-i+1,j];
end;
b[count]:=sum;
end;

Автор: Relrin 3.12.2010 1:03

UP!!!

Автор: Lapp 3.12.2010 4:10

Цитата(Relrin @ 2.12.2010 13:40) *
Спасибо! Немного уже раскрутил задачу с твоей помощью. Только проблема с подсчетом неквадратной матрицы осталась, т.к. подсчеты неправильные идут уже с первого элемента
ЧТООО???... Эй, приятель.. Ты даешь себе отчет в том, что делаешь и пишешь?..
Я тебе дал ДВА ВЕРНЫХ РЕШЕНИЯ С ПОДРОБНЫМИ КОММЕНТАРИЯМИ. Они БЕЗУСЛОВНО работают со всеми матрицами любых соотношений длины и ширины. От тебя требовалось только переменные описать и ввести/вывести результат. Ты даже этого, не смог сделать, up'ник..

Хорошо, дополняю эти решения до целых программ.

Решение с обходом по контурам.
const
m=3;
n=4;
l=(m+n-1) div 4 +1;

var
a: array [1..m,1..n] of integer;
i,j,d: integer;
b: array [1..l] of integer;

begin
for i:=1 to m do begin
for j:=1 to n do begin
a[i,j]:=Random(10);
Write(a[i,j]:4)
end;
WriteLn
end;
WriteLn;
if m<n then d:=(m-1)div 2+1 else d:=(n-1)div 2+1; // calculate contours amount (size of b)
for i:=1 to d do begin // cycle through contours
for j:=i to m-i+1 do begin // rows
Inc(b[i],a[j,i]);
if i<n-i+1 then Inc(b[i],a[j,n-i+1]); // do not count last line twice
end;
for j:=i+1 to n-i do begin // columns
Inc(b[i],a[i,j]);
if i<m-i+1 then Inc(b[i],a[m-i+1,j]); // do not count last column twice
end
end;
for i:=1 to d do Write(b[i]:4);
ReadLn
end.


Решение со сквозным подсчетом (лучше).
const
m=4;
n=4;
l=(m+n-1)div 4+1;

var
a: array [1..m,1..n] of integer;
i,j,k,d: integer;
b: array [1..l] of integer;

begin
for i:=1 to m do begin
for j:=1 to n do begin
a[i,j]:=Random(10);
Write(a[i,j]:4)
end;
WriteLn
end;
WriteLn;
if m<n then d:=(m-1)div 2+1 else d:=(n-1)div 2+1; // calculating the b size
for i:=1 to m do for j:=1 to n do begin
k:=d; // set to max possible
if i<k then k:=i; // top distance
if j<k then k:=j; // left distance
if m-i+1<k then k:=m-i+1; // bottom distance
if n-j+1<k then k:=n-j+1; // right distance
Inc(b[k],a[i,j]); // adding to summ array
end;
for i:=1 to d do Write(b[i]:4);
ReadLn
end.


И кончай тут Up'ать каждый час. Тут не слепые собрались. Есть, что сказать - говори. А понукать будешь лошадей, когда сапоги выдадут..

-1 за нежелание вникать в ответы..