Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
алгоритмы1.docx
Скачиваний:
42
Добавлен:
10.06.2015
Размер:
2 Мб
Скачать
☆

43. Алгоритм Прима построения одмс.

В алгоритме последовательно строится множество вершин U, из которого пореберно вырастает остовное дерево. Пусть V={1, 2, 3, … , n}; U={1}. На каждом шаге находим {u, v} наименьшей стоимости, у которого u принадлежит U, v принадлежит V/U, после чего v переносится из множества V/U в множество U. Алгоритм завершается когда U=V.

Псевдокод алгоритма Прима:

procedure Prim (G: <граф>; T: <множество ребер дерева>);

var

U: < … >;

v, u: <выршины>;

begin

T:= ø;

U:= {1};

while U=V do begin

<нахождение ребра {u, v} среди ребер u принадлежит U; v принадлежит V/U>

T:=T пересекается(U) с {u, v};

U:=v пересекается с {v};

end;

end; // конец алгоритма Прима

Для реализации алгоритма множества введем 2 массива:

  • Rib_u-i элемент Rib_u-i [i] содержит вершины u принадлежит U соединен ребром с вершиной i i принадлежит V/U соедин. ребром имеющим наименьшую стоимость у которой одна вершина i зафиксирована, а i принадлежит V/U переменная

  • LowCost [i] содержит значение стоимости ребра {Rib_u-i, i}.

Заполним ячейки массива Rib_u-i и LowCost индексированными номерами тех вершин, которые на данном этапе находятся в множестве V/U. На каждом шаге алгоритм просматривает массив LowCost находящий наименьшие значение LowCost[k], k принадлежит V/U и соединен ребром с вершиной из множества U. Ребро (k, Rib_u-i[k]) выводится на печать, массивы Rib_u-i и LowCost корректируются с учетом перехода k в U. На вход алгоритму подается матрица стоимостей исходного графа. Если какое-то ребро отсутствует, то его длину обозначим как очень большое число, которое будем хранить в памяти как iтfinity.

Рассмотрим фрагмент кодов:

const n=10 Double0;

infinity = 1.0E + 300;

type

StoimRib_u-i = array [1..n, 1..n] of Double;

procedure Prim (C: StoimRib); //данная процедура последовательно определяет и распечатывает ребра ОДМС

var

LowCost: array [1..n] of Double;

Rib_u-i: array [1..n] of Double;

i, j, k: Integer;

min: Double;

begin // начальное запоминание LowCost, с учетом, что в начале в множество U входит только 1-я вершина

for i:=2 to n do begin

LowCost[i]:= c[1, i];

Rib_u-i[i]:=1;

end;

Далее идет последовательный поиск ребер ОДМС.

for i:=2 to n do begin

Далее идет поиск в V/U вершина k имеет инцидентное ребро заканчивающееся в множестве U, при условии, что ребро имеет наименьшую стоимость среди рассматриваемых:

min:= LowCost[i];

k:=2;

for j:=3 to n do

if LowCost[j] < min then begin

min:=LowCost[j];

k:=j;

end;

PRINT (Rib_u-i[k], k);

LowCost[k]:=infinity; //благодаря искусственному изменению величин k будет интерпретироваться, как добавленное к U.

for j:=2 to n do

if (c[k, j] < LowCost[j])

end

LowCost[j] < infinity >) then begin

LowCost[j]:=c[k, j];

Rib_u-i[j]:=k;

end;

end;

end; //конец алгоритма Прима

Работа алгоритма иллюстрируется на рис. 5.2, где строится ОДМС для графа изображенного на рис. 5.1(а)

Рис. 5.2

44. Понятие задачи коммивояжера. Жадный алгоритм для приближенного решения задачи коммивояжера.

Задача коммивояжера формулируется так: в приближенном алгоритме найти гамильтонов цикл имеющий минимальную стоимость. Возможно, что нет ни одного гамильтонова цикла.

Эта задача относится к классу дискретной математики. В таких задачах опред. решение наход. знач. алг., в котором некоторая целивая функция достигается минимум или максимумn F(z).

ООФ – множество всех гамильтоновых циклов

ОЗФ – множество чисел

Задача нахождения гамильтонова цикла является NP – полной, а значит является задачей коммивояжера, т.е для нее не существует или не найден полиномиальный алгоритм определения оптимального решения => если задача имеет большую размерность, то перебор всех допустимых решений за приемлемое время не реализуется => необходим алгоритм, который дает приблизительное решение, но за приемлемое время.

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

  1. Либо захватить больше или быстрее какого-то ресурса

  2. Либо сохранить в резерве как можно больше ресурса

  3. Либо как можно меньше нарастить значение целевой функции в задаче на минимализацию. В частности жадный алгоритм для задачи коммивояжера на каждом шаге ищет самое короткое из тех, которые можно включить в цикл.

Основные элементы для данной задачи сводятся к следующим правилам выбора очередного ребра при построении гамильтонова цикла:

  1. Добавление ребра не должно приводить к появлению в маршруте к вершине со степенью 3

  2. Добавление ребра не превращает строящийся маршрут в цикл не являющийся гамильтоновым

При невыполнении указанных правил наикратчайшее ребро еще не включенное в цикл отбрасывается и выбирается наикратчайшее из оставшихся. Если по этим правилам удастся построить цикл, то он будет гамильтоновым, этот цикл и принимается приближенным в задаче коммивояжера. Даже если есть минимальный цикл, то не факт, что жадный алгоритм найдет хотя бы 1 такой цикл.