Смекни!
smekni.com

работа по дисциплине «Технологии программирования» на тему: «Фибоначчиевы кучи» (стр. 4 из 4)

const CH: array [1..6] of string[3]=

('1-я', '2-я', '3-я',

'4-я', '5-я', '6-я');

procedure TForm1.Button4Click(Sender: TObject); // задает пути между частями случайным образом

var

i, j: integer;

flag: real; // существует ли путь

begin

for i:=1 to StringGrid1.ColCount-1 do

begin

for j:=i+1 to StringGrid1.RowCount-1 do

begin

flag := random;

if (flag>0.5) then

begin

StringGrid1.Cells[i,j] := IntToStr(random(MAX));

StringGrid1.Cells[j,i] := StringGrid1.Cells[i,j];// заполняет таблицу

end;

end;

end;

end;

procedure TForm1.GetWeightsMatrix; // заполняет матрицу весов Weights

var

i, j: integer;

begin

for i:=0 to CHCount-1 do

Weights[i,i] := 0; // из части в саму себя

for i:=0 to CHCount-1 do

for j:=0 to CHCount-1 do

begin

if (StringGrid1.Cells[i + 1, j + 1] <> '') then

Weights[i, j] := StrToInt(StringGrid1.Cells[i + 1, j + 1]);

end;

end;

procedure TForm1.Button6Click(Sender: TObject); вызывает процедуры для расчета

begin

Memo1.Lines.Clear;

GetWeightsMatrix; // перебрасывает пути в матрицу

FirstCountStep; // инициализирует расчет

StraightWay; // находит прямые пути

GoCount; // запускает расчет

end;

procedure TForm1.FirstCountStep; // проверяет, выбрана ли часть из списка

var

i: integer;

begin

first := -1;

for i := 0 to CHCount - 1 do

begin

if ListBox1.Selected[i] then

first := i;

end;

if (first = -1) then

begin

MessageDlg(‘ ошибка: вы не выбрали начальную часть в списке!',

mtError, [mbOK], 0);

exit;

end;

end;

procedure TForm1.FormCreate(Sender: TObject); // задает части в интерфейсе

var

i: integer;

begin

StringGrid1.Cells[0, 0] := 'часть';

for i:= 1 to CHCount do

begin

StringGrid1.Cells[0, i] := CH[i];

StringGrid1.Cells[i, 0] := CH[i];

Listbox1.Items[i-1] := CH[i];

end;

end;

procedure TForm1.StraightWay; // находит прямой путь

var

i : integer;

begin

for i:= 1 to CHCount do

begin

if Weights[first, i] <> 0 then

Memo1.lines.Add(ListBox1.Items[first] + '=>' + INtToStr(i) +

'(' + IntToStr(Weights[first, i]) + ')');

end;

end;

procedure TForm1.GoCount; // находит непрямой путь между частями и вычисляет расстояние

var

i, n, j : integer;

str : string;

begin

n := 0;

str := (ListBox1.Items[first] + '=>');

for j := 1 to CHCount do

begin

for i := 0 to CHCount-1 do

begin

if Weights[first, i] <> 0 then

if Weights[i, j] <> 0 then

begin

n := n + Weights[first, i] + Weights[i, j];

str := str + ListBox1.items[i] + '=>';

end;

end;

Memo1.Lines.Add(str + IntToStr(j) + '('+IntToStr(n)+')')

end;

end;

procedure TForm1.Button1Click(Sender: TObject); // очистка

var

i, j: integer;

begin

for i:= 1 to CHCount do

for j:= 1 to CHCount do

begin

StringGrid1.Cells[j, i] := '';

end;

Memo1.Lines.Clear;

end;

end.

Приложение 2. Тестовое задание.

Рассмотрим выполнение алгоритма на примере графа, показанного на рисунке. Пусть требуется найти расстояния от 1-й вершины до всех остальных.

Кружками обозначены вершины, линиями — пути между ними (ребра графа). В кружках обозначены номера вершин, над ребрами обозначена их «цена» — длина пути. Рядом с каждой вершиной красным обозначена метка — длина кратчайшего пути в эту вершину из вершины 1.

Первый шаг . Рассмотрим шаг алгоритма Дейкстры для нашего примера. Минимальную метку имеет вершина 1. Ее соседями являются вершины 2, 3 и 6.

Первый по очереди сосед вершины 1 — вершина 2, потому что длина пути до нее минимальна. Длина пути в нее через вершину 1 равна кратчайшему расстоянию до вершины 1 + длина ребра, идущего из 1 в 2, то есть 0 + 7 = 7. Это меньше текущей метки вершины 2, поэтому новая метка 2-й вершины равна 7.

Аналогичную операцию проделываем с двумя другими соседями 1-й вершины — 3-й и 6-й.

Все соседи вершины 1 проверены. Текущее минимальное расстояние до вершины 1 считается окончательным и обсуждению не подлежит (то, что это действительно так, впервые доказал Дейкстра ). Вычеркнем её из графа , чтобы отметить, что эта вершина посещена.

Второй шаг' . Шаг алгоритма повторяется. Снова находим «ближайшую» из непосещенных вершин. Это вершина 2 с меткой 7.

Снова пытаемся уменьшить метки соседей выбранной вершины, пытаясь пройти в них через 2-ю. Соседями вершины 2 являются 1, 3, 4.

Первый (по порядку) сосед вершины 2 — вершина 1. Но она уже посещена, поэтому с 1-й вершиной ничего не делаем.

Следующий сосед вершины 2 — вершина 4. Если идти в неё через 2-ю, то длина такого пути будет = кратчайшее расстояние до 2 + расстояние между вершинами 2 и 4 = 7 + 15 = 22. Поскольку 22<

, устанавливаем метку вершины 4 равной 22.

Ещё один сосед вершины 2 — вершина 3. Если идти в неё через 2, то длина такого пути будет = 7 + 10 = 17. Но текущая метка третьей вершины равна 9<17, поэтому метка не меняется.

Все соседи вершины 2 просмотрены, замораживаем расстояние до неё и помечаем ее как посещенную.

Третий шаг . Повторяем шаг алгоритма, выбрав вершину 3. После ее «обработки» получим такие результаты:

Дальнейшие шаги . Повторяем шаг алгоритма для оставшихся вершин (Это будут по порядку 6, 4 и 5).

Завершение выполнения алгоритма . Алгоритм заканчивает работу, когда вычеркнуты все вершины. Результат его работы виден на последнем рисунке: кратчайший путь от вершины 1 до 2-й составляет 7, до 3-й — 9, до 4-й — 20, до 5-й — 20, до 6-й — 11.