Помощь - Поиск - Пользователи - Календарь
Полная версия: Ошибка 205 ...
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
kent
Дана задача: Дано множество A из N точек. Найти наименьший|наибольший периметр треугольника, вершины которого принадлежат различным точкам множества A, и сами эти точки (точки выводятся в том же порядке, в котором они перечислены при задании множества A). Я её сделал, но если задать четыре точки (N=4), то компилятор выдает ошибку 205 ... Это так должно быть или у меня в решении ошибка?
Malice
Цитата(kent @ 26.07.05 13:13)
Это так должно быть или у меня в решении ошибка?

Если у тебя ошибка, то так быть точно не должно :D Как ты делал ?
kent
Вот решение:

uses crt;
type
  TPoint = record
  x,y,id : Integer;
  end;
type
  TIndex = record
  first,second,third : Integer;
  end;

{---------------------------------------}
Function Space(a,b : TPoint) : Double;
begin
     Space := sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));
end;
{---------------------------------------}

{---------------------------------------}
Function Range(a,b : Integer) : Extended;
var fac_a,fac_b,fac_dif : Extended;
    p1,p2,p3 : Integer;
begin
     fac_a := 1; p1 := 1;
     repeat
       inc(p1);
       fac_a := fac_a * p1;
     until p1 = a;
     fac_b := 1; p2 := 1;
     repeat
       inc(p2);
       fac_b := fac_b * p2;
     until p2 = b;
     fac_dif := 1; p3 := 1;
     repeat
       inc(p3);
       fac_dif := fac_dif * p3;
     until p3 = a - b;
     Range := fac_a / (fac_b * fac_dif);
end;
{---------------------------------------}

var a : array [1..1000] of TPoint;
    id : array[1..1000] of TIndex;
    Perimeter : array [1..1000] of Double;
    N,i,j,m : Integer;
    indx,count_indx : Integer;
    max_Perimeter,min_Perimeter : Double;
    min_id,max_id : TIndex;
begin
     {$R+}
     Clrscr;
     Write('Input N:');
     ReadLn(N);
     WriteLn('Input set A:');
     for i := 1 to N do begin
        Write('Point <',i,'> (X,Y):');
        Read(a[i].x,a[i].y);
        a[i].id := i;
     end;
     m := 3;
     for i := 1 to m do a[i].id := i;
     indx := 0;
     repeat
       inc(indx);
       for i := 1 to m do
          if (i > 2) then begin
            id[indx].first := a[i - 2].id;
            id[indx].second := a[i - 1].id;
            id[indx].third := a[i].id;
          end;
       Perimeter[indx] := Space(a[a[i - 2].id],a[a[i - 1].id]) +
                          Space(a[a[i - 1].id],a[a[i].id]) +
                          Space(a[a[i - 2].id],a[a[i].id]);
       i := m;
       while (i > 1) and (a[i].id = N - m + i) do dec(i);
       inc(a[i].id);
       for j := i + 1 to m do a[j].id := a[j - 1].id + 1;
     until (i = 0) or (indx = 1000) or (indx = Range(N,m));
     count_indx := indx;
     min_Perimeter := 500000;
     max_Perimeter := 0;
     for indx := 1 to count_indx do begin
        if (Perimeter[indx] < min_Perimeter) then begin
          min_Perimeter := Perimeter[indx];
          min_id.first := id[indx].first;
          min_id.second := id[indx].second;
          min_id.third := id[indx].third;
        end;
        if (Perimeter[indx] > max_Perimeter) then begin
          max_Perimeter := Perimeter[indx];
          max_id.first := id[indx].first;
          max_id.second := id[indx].second;
          max_id.third := id[indx].third;
        end;
     end;
     WriteLn;
     WriteLn('------------------------------------------');
     WriteLn('Min perimeter:',min_Perimeter,';');
     WriteLn('Min perimeter points: ',min_id.first,'-',min_id.second,'-',min_id.third,';');
     WriteLn('*******************************************');
     WriteLn('Max perimeter:',max_Perimeter,';');
     WriteLn('Max perimeter points: ',max_id.first,'-',max_id.second,'-',max_id.third,';');
     WriteLn('-------------------------------------------');
     Readkey;
end.



Malice
Цитата(kent @ 26.07.05 13:40)
Вот решение:

Ой, опять кучу массивов нагородил, зачем ?

Перебор делай так:

for I:=1 to n-2 do
 for j:=i+1 to n-1 do
  for k:=j+1 to n do begin
pr:=space(i,j)+space(j,k)+space(k,i);
{ тут же сравниваешь на мин и макс и сохраняешь i, j и k в переменных, например min1, min2, min3 и max1, max2, max3
}
end;
{все, здесь уже результат выводишь }



И не нужны тебе массивы, кроме "A". Из TPoint id тоже выкинь, зачем он там?
kent
А что уменя вообще неправильно что ли?

Цитата
Ой, опять кучу массивов нагородил, зачем ?

Перебор попроще просто не знал...
volvo
kent, ты все время описываешь массивы заведомо бОльшего размера, чем тебе нужно. А зачем? Есть же более удобные способы smile.gif
Type
  TPoint = Record
    { твое описание ... }
  End;
  PArrPoint = ^ArrPoint;
  ArrPoint = Array[0 .. Pred(maxInt Div SizeOf(TPoint))] Of TPoint;

...
Var
  arr: PArrPoint;
...
  { вводишь размерность массива: N }
  { и размещаешь массив в "куче" }
  GetMem(arr, N * SizeOf(TPoint));
  {
    и так же, как ты работал со своим массивом,
    работаешь с массивом расположенным в "куче",
    просто вместо arr[i] делаешь arr^[i], и не надо 
    никаких массивов по 1000 элементов...
  }

...
  { по окончании работы с массивом - осввобождаешь память }
  FreeMem(arr, N * SizeOf(TPoint));
...
kent
volvo, а что такое куча?
Malice
Цитата(kent @ 26.07.05 14:15)
Перебор попроще просто не знал...

Теперь знаешь smile.gif Проще исправить, чем ошибку найти, имхо.
А volvo дело говорит, так делай, или не вводи N вообще, а выведи в константы.
kent
Надо ещё теорию подучить...
Malice
Если не хочешь исправлять, то так:

Function Range(a,b : Integer) : Extended;
.............
     fac_dif := 1; 
p3 := 1; 
     repeat
       inc(p3);
       fac_dif := fac_dif * p3;
     until p3 = a - b;
.............
end;


В выделенном фрагменте поставь p3=0; иначе если (a-B )=1 у тебя сразу p3 становится=2 и цикл крутится ооочень долго smile.gif.
И еще, в Tpoint поставь тип longint, а то функция space может лажаться.
kent
Malice, спасибо... :thanks:
Теперь вроде врубаюсь почему при (N=4) выдает ошибку...
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.