Цель лекции: изучить основные алгоритмы поиска
Нахождение
Рассмотрим три наиболее
Указанные алгоритмы легко выполняются при малом количестве вершин в графе. При увеличении их количества задача поиска
Данный алгоритм является алгоритмом на графах, который изобретен нидерландским ученым Э. Дейкстрой в 1959 году. Алгоритм находит кратчайшее расстояние от одной из
Каждой вершине приписывается вес – это вес пути от начальной вершины до данной. Также каждая вершина может быть выделена. Если вершина выделена, то путь от нее до начальной вершины кратчайший, если нет – то временный.
Алгоритм Дейкстры
Шаг 1. Всем вершинам, за исключением первой, присваивается вес равный бесконечности, а первой вершине – 0.
Шаг 2. Все вершины не выделены.
Шаг 3. Первая вершина объявляется текущей.
Шаг 4. Вес всех невыделенных вершин пересчитывается по формуле: вес невыделенной вершины есть минимальное число из старого веса данной вершины, суммы веса текущей вершины и веса
Шаг 5. Среди невыделенных вершин ищется вершина с минимальным весом. Если таковая не найдена, то есть вес всех вершин равен бесконечности, то маршрут не существует. Следовательно, выход. Иначе, текущей становится найденная вершина. Она же выделяется.
Шаг 6. Если текущей вершиной оказывается конечная, то путь найден, и его вес есть вес конечной вершины.
Шаг 7. Переход на шаг 4.
В программной реализации S вершин, для которых кратчайшие пути от начальной вершины уже известны. На каждом шаге к множеству S добавляется та из оставшихся вершин, расстояние до которой от начальной вершины меньше, чем для других оставшихся вершин. При этом будем использовать массив D, в который записываются длины S будет содержать все вершины графа, тогда массив D будет содержать длины
Помимо указанных массивов будем использовать C, где элемент C[i,j] –длина (i,j), если C представляет собой
Для определения самого
(рис 45.1) Демонстрация алгоритма Дейкстры//Описание функции алгоритма Дейкстры
void Dijkstra(int n, int **Graph, int Node){
bool *S = new bool[n];
int *D = new int[n];
int *P = new int[n];
int i, j;
int Max_Sum = 0;
for (i = 0 ; i < n ; i++)
for (j = 0 ; j < n ; j++)
Max_Sum += Graph[i][j];
for (i = 0 ; i < n ; i++)
for (j = 0 ; j < n ; j++)
if (Graph[i][j] == 0)
Graph[i][j] = Max_Sum;
for (i = 0 ; i < n ; i++){
S[i] = false;
P[i] = Node;
D[i] = Graph[Node][i];
}
S[Node] = true;
P[Node] = -1;
for ( i = 0 ; i < n - 1 ; i++ ){
int w = 0;
for ( j = 1 ; j < n ; j++ ){
if (!S[w]){
if (!S[j] D[j] <= D[w])
w = j;
}
else w++;
}
S[w] = true;
for ( j = 1 ; j < n ; j++ )
if (!S[j])
if (D[w] + Graph[w][j] < D[j]){
D[j] = D[w] + Graph[w][j];
P[j] = w;
}
}
for ( i = 0 ; i < n ; i++ )
printf("%5d",D[i]);
cout << endl;
for ( i = 0 ; i < n ; i++ )
printf("%5d",P[i]+1);
cout << endl;
delete [] P;
delete [] D;
delete [] S;
}
Сложность
Если для представления графа использовать O(n2), где n – количество
Рассматриваемый алгоритм иногда называют
Этот алгоритм более общий по сравнению с алгоритмом Дейкстры, так как он находит кратчайшие пути между любыми двумя
В алгоритме Флойда используется матрица A размером nxn, в которой вычисляются длины A[i,j] равен расстоянию от вершины i к вершине j, которое имеет конечное значение, если существует (i,j), и равен бесконечности в противном случае.
Алгоритм Флойда
Основная идея алгоритма. Пусть есть три вершины i, j, k и заданы расстояния между ними. Если выполняется неравенство A[i,k]+A[k,j]<A[i,j], то целесообразно заменить путь i->j путем i->k->j. Такая замена выполняется
Шаг 0. Определяем начальную матрицу расстояния A0 и матрицу последовательности вершин S0. Каждый диагональный элемент обеих матриц равен 0, таким образом, показывая, что эти элементы в вычислениях не участвуют. Полагаем k = 1.
Основной шаг k. Задаем строку k и столбец k как ведущую строку и ведущий столбец. Рассматриваем возможность применения замены описанной выше, ко всем элементам A[i,j] матрицы Ak-1. Если выполняется неравенство $$A[i,k]+A[k,j]<A[i,j], (i\ne k, j\ne k, i\ne j)$$, тогда выполняем следующие действия:
Ak путем замены в матрице Ak-1 элемента A[i,j] на сумму A[i,k]+A[k,j] ;Sk путем замены в матрице Sk-1 элемента S[i,j] на k. Полагаем k = k + 1 и повторяем шаг k.Таким образом,
(рис 45.2) Демонстрация алгоритма Флойда//Описание функции алгоритма Флойда
void Floyd(int n, int **Graph, int **ShortestPath){
int i, j, k;
int Max_Sum = 0;
for ( i = 0 ; i < n ; i++ )
for ( j = 0 ; j < n ; j++ )
Max_Sum += ShortestPath[i][j];
for ( i = 0 ; i < n ; i++ )
for ( j = 0 ; j < n ; j++ )
if ( ShortestPath[i][j] == 0 i != j )
ShortestPath[i][j] = Max_Sum;
for ( k = 0 ; k < n; k++ )
for ( i = 0 ; i < n; i++ )
for ( j = 0 ; j < n ; j++ )
if ((ShortestPath[i][k] + ShortestPath[k][j]) <
ShortestPath[i][j])
ShortestPath[i][j] = ShortestPath[i][k] +
ShortestPath[k][j];
}
Заметим, что если граф неориентированный, то все матрицы, получаемые в результате преобразований симметричны и, следовательно, достаточно вычислять только элементы, расположенные выше главной диагонали.
Если граф представлен O(n3), поскольку в нем присутствуют вложенные друг в друга три цикла.
Переборные алгоритмы по сути своей являются алгоритмами поиска, как правило, поиска оптимального решения. При этом решение конструируется постепенно. В этом случае обычно говорят о переборе вершин дерева вариантов. Вершинами такого графа будут промежуточные или конечные варианты, а
Рассмотрим переборные алгоритмы, основанные на методах поиска в графе, на примере задачи нахождения
Постановка задачи.
Лабиринт, состоящий из проходимых и непроходимых клеток, задан матрицей A размером mxn. Элемент матрицы A[i,j]=0, если клетка (i,j) проходима. В противном случае $$A[i,j]=\infty$$.
Требуется найти длину (1, 1) в клетку (m, n).
Фактически дана
Вершинами дерева вариантов в данной задаче являются пути, начинающиеся в клетке (1, 1). k и k+1, где второй путь получается из первого добавлением к пути еще одного хода.
Перебор с возвратом
Данный метод основан на методе
Также необходим массив Dist, размерность которого соответствует количеству
Пусть текущей является некоторая клетка (в начале работы алгоритма – клетка (1, 1) ). Если для текущей клетки есть клетка-сосед , отсутствующая в Way, в которую на этом пути еще не ходили, то добавляем в Way и текущей клетке присваиваем , иначе извлечь из Way.
Приведенное выше описание дает четко понять, почему этот метод называется перебором с возвратом. Возврату здесь соответствует операция "извлечь из Way ", которая уменьшает длину Way на 1.
Перебор заканчивается, когда Way пуст и делается попытка возврата назад. В этой ситуации возвращаться уже некуда (рис 45.3).
Way является текущим путем, но в процессе работы необходимо хранить и оптимальный путь OptimalWay.
Усовершенствование алгоритма можно произвести следующим образом: не позволять, чтобы длина Way была больше или равна длине OptimalWay. В этом случае, если и будет найден какой-то вариант, он заведомо не будет оптимальным. Такое усовершенствование в общем случае означает, что как только текущий путь станет заведомо неоптимальным, надо вернуться назад. Данное улучшение алгоритма позволяет во многих случаях сильно сократить перебор.

(рис ) Демонстрация алгоритма перебора с возвратом(рис 45.3) /*Описание функции переборного алгоритма методом поиска в глубину */ void Backtracking(int n, int m, int **Maze){ int Begin, End, Current; Begin = (n - 1) * m; End = m - 1; int *Way, *OptimalWay; int LengthWay, LengthOptimalWay; Way = new int[n*m]; OptimalWay = new int[n*m]; LengthWay = 0; LengthOptimalWay = m*n; for (int i = 0 ; i < n*m ; i++ ) Way[i] = OptimalWay[i] = -1; int *Dist; Dist = new int[n*m]; for (int i = 0 ; i < n ; i++ ) for (int j = 0 ; j < m ; j++ ) Dist[i * m + j] = ( Maze[i][j] == 0 ? 0 : -1 ); Way[LengthWay++] = Current = Begin; while ( LengthWay > 0 ){ if(Current == End){ if (LengthWay < LengthOptimalWay){ for (int i = 0 ; i < LengthWay ; i++ ) OptimalWay[i] = Way[i]; LengthOptimalWay = LengthWay; } if (LengthWay > 0) Way[--LengthWay] = -1; Current = Way[LengthWay-1]; } else{ int Neighbor = -1; if ((Current/m - 1) >= 0 !Insert(Way, Current - m) (Dist[Current - m] == 0 || Dist[Current - m] > LengthWay) Dist[Current] < LengthOptimalWay) Neighbor = Current - m; else if ((Current%m - 1) >= 0 !Insert(Way,Current - 1) (Dist[Current - 1]== 0 || Dist[Current - 1] > LengthWay) Dist[Current] < LengthOptimalWay ) Neighbor = Current - 1; else if ((Current%m + 1) < m !Insert(Way,Current + 1) (Dist[Current + 1]== 0 || Dist[Current + 1] > LengthWay) Dist[Current] < LengthOptimalWay ) Neighbor = Current + 1; else if ((Current/m + 1) < n !Insert(Way,Current + m) (Dist[Current + m]== 0 || Dist[Current + m] > LengthWay) Dist[Current] < LengthOptimalWay ) Neighbor = Current + m; if ( Neighbor != -1 ){ Way[LengthWay++] = Neighbor; Dist[Neighbor] = Dist[Current] + 1; Current = Neighbor; } else { if (LengthWay > 0) Way[--LengthWay] = -1; Current = Way[LengthWay-1]; } } } if ( LengthOptimalWay < n*m ) cout << endl << "Yes. Length way=" << LengthOptimalWay<< endl; else cout << endl << "No" << endl; }
Волновой алгоритм
Этот переборный алгоритм, который основан на
Распространение волны и есть собственно поиск в ширину, при котором клетки помечаются номером шага метода, на котором клетка посещается. При обратном ходе, начиная с конечной вершины, идет восстановление пути, по которому в нее попали путем включения в него клеток с минимальной пометкой (рис 45.4). Важной особенностью является то, что восстановление начинается с конца (с начала оно зачастую невозможно).
(рис 45.4) Демонстрация волнового алгоритмаЗаметим, что перебор методом
Алгоритм Дейкстры – это алгоритм нахождения
Алгоритм Флойда – это алгоритм поиска
Волновой алгоритм – это переборный алгоритм, который основан на
Кратчайший путь – это путь в графе, то есть последовательность вершин и ребер,
Переборный алгоритм – это алгоритм
O(n3).Цель работы: изучить основные алгоритмы поиска
При выполнении лабораторной работы для каждого задания требуется написать программу на языке С++, которая получает на входе числовые данные, выполняет их обработку в соответствии с требованиями задания и выводит результат на экран. Для обработки данных необходимо реализовать алгоритмы поиска
Теоретические сведения.
Ознакомьтесь с материалом лекции 45.
Задания к лабораторной работе.
Выполните приведенные ниже задания.

MxN и покрыто мелкими островками. В левом верхнем углу находится плот размером mxm . За один шаг плот может передвигаться на одну клетку по вертикали или горизонтали. Требуется определить Указания к выполнению работы.
Каждое задание необходимо решить в соответствии с изученными алгоритмами поиска
Следует реализовать каждое задание в соответствии с приведенными этапами:
Требования к отчету.
Отчет по лабораторной работе должен соответствовать следующей структуре.
Контрольные вопросы
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.