Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Работа с массивом.


Автор: Jovi 22.12.2006, 20:51
Есть такая задачка.

Есть массив 1000 на 1000 из единичек и ноликов.
В нем нужно найти все "сгустки" единичек в количестве до 50 штук и заменить их на нолики.

Под сгустком единичек понимаеются непосредственно прилегающие друг к другу единички вне зависимости от того, с какой стороны они прилегают.

Таким образом в результате всей операции должны остаться только очень большие сгустки единичек в массиве, а маленькие сгустки единичек умереть в нолики.

Господа, что посоветуете?
Заранее Вам благодарен.

Автор: S.A.G. 23.12.2006, 00:36
Допустим массив называеться Mas и начинаеться с нуля. Тогда адресация элементов будет в пределах от 0 до 999.

Код

i:= 0; //адресует массив
repeat
  if Mas[i] = 1 then
    begin 
      for k:= i + 1 to 999 do
        if Mas[k] = 0 then
          break;      
      if (k - i < 50) and (Mas[k] = 0) then //последним условием страхуемся от случая когда k = 999
        for j:= i to k - 1 do
          Mas[j]:= 0;
      i:= k + 1
    end;
until i > 999


Ааа блин втыкнул.. это для одномерного массива решение задачи. Надеюсь наведет на какую-то мысль.. Задача должна быть стопудофф решаемая.. просто нужно увеличить размерность а мыслить также.

P.S. Можешь подождать пока кто-нибудь додумаеться или у меня снова появиться желание заглянуть в эту тему. smile

Автор: MetalFan 23.12.2006, 19:29
накидал ради развития алгоритм для замены всех "скоплений" единиц колвом > 1 на нули.
можешь модифицировать для замены с подсчетом)
надо?

Автор: MetalFan 25.12.2006, 09:49
вот небольшой примерчик)
"убивает" все скопления единичек кол-вом > 1
Код

unit Unit1;

interface
  uses SysUtils, windows;

const
  C_ArrHigh = 10; //размерность массива C_ArrHigh * C_ArrHigh


type
  TSourceArray = array [1..C_ArrHigh, 1..C_ArrHigh] of byte; //integer

//заменяет все скопления единиц в массиве кол-вом > 1, возвращает кол-во замененных единиц.
function FindReplaceTrueBundle( var Arr: TSourceArray ): Integer;

procedure SaveArrToFile( const AFileName: string; Arr: TSourceArray );

implementation


function FindReplaceNeighbours( var Arr: TSourceArray; AI, AJ, APrevI, APrevJ: Integer ): Integer;
var
  lCount: Integer;
  lNextI, lNextJ: Integer;
  lFirst: Boolean;
begin

  Result := 0;
  if Arr[AI, AJ] = 0 then Exit; //если ноль - то и не смотрим ничего
  lFirst := (APrevI = -1) and (APrevJ = -1); //первая единица, найденная перебором

  //сразу сбрасываем текущий элемент, чтобы не попасть в бесконечную рекурсию в случае
  //  1 1
  //  1 1 b т.п.
  Arr[AI, AJ] := 0;

  if not lFirst  then  //если не первая, значит считаем, что нашли одну единиц
    Result := 1;
  //далее проверяем соседние элементы...
  lNextI := pred( AI );
  lNextJ := AJ;
  if (AI > 1) and (( APrevI <> lNextI) or (APrevJ <> lNextJ)) then
  begin
    lCount := FindReplaceNeighbours( Arr, lNextI, lNextJ, AI, AJ );
    Inc( Result, lCount);
  end;

  lNextI := AI;
  lNextJ := pred( AJ );
  if (AJ > 1) and (( APrevI <> lNextI) or (APrevJ <> lNextJ)) then
  begin
    lCount := FindReplaceNeighbours( Arr, lNextI, lNextJ, AI, AJ );
    Inc( Result, lCount);
  end;

  lNextI := succ(AI);
  lNextJ := AJ;

  if (AI < C_ArrHigh) and (( APrevI <> lNextI) or (APrevJ <> lNextJ)) then
  begin
    lCount := FindReplaceNeighbours( Arr, lNextI, lNextJ, AI, AJ );
    Inc( Result, lCount);
  end;

  lNextI := AI;
  lNextJ := succ( AJ );
  if (AJ < C_ArrHigh)and (( APrevI <> lNextI) or (APrevJ <> lNextJ)) then
  begin
    lCount := FindReplaceNeighbours( Arr, lNextI, lNextJ, AI, AJ );
    Inc( Result, lCount);
  end;
  //

  if lFirst then
    if (Result > 0) then // если первый элемент и найдены соседние - то увеличиваем счетчик
      Inc( Result )
    else
      Arr[AI, AJ] := 1; //иначе восстанавливаем отдельно стоящую единицу
end;

function FindReplaceTrueBundle( var Arr: TSourceArray ): Integer;
  var
    i, j: integer;
    lCount: Integer;
  begin
    Result := 0;
    for i := 1 to C_ArrHigh do
      for j := 1 to C_ArrHigh do
      begin
        lCount := FindReplaceNeighbours( Arr, i, j, -1, -1 );
        Inc( Result, lCount );
      end;
  end;

procedure SaveArrToFile( const AFileName: string; Arr: TSourceArray );
var
  i, j: Integer;
  lTextFile: Text;
  lChr: Char;
begin
  Assign( lTextFile, AFileName );
  try
    Rewrite( lTextFile );
    for i := 1 to C_ArrHigh do
    begin
      for j := 1 to C_ArrHigh do
      begin
        lChr := '0';
        if Arr[ i, j] = 1 then
          lChr := '1';
        Write( ltextfile, lChr, ' ');
      end;
      Writeln( ltextfile );
    end;

  finally
    CloseFile( lTextFile );
  end;
end;

end.

Автор: Jovi 26.12.2006, 21:10
Попробую и обязательно напишу ответ.
Я его попробую переделать, чтоб решал мою задачу - увивал все скопления от 1 до 20, скажем, а большие оставлял. Тое сть если представить это в виде картинки - убивал все точки и помехи, а оставлял большие линии и рисунки.

Автор: Демо 27.12.2006, 12:02
Jovi, 

Соседние точки, лежащие рядом по диагонали, учитывать?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)