Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лаб. 3 АиСД (Вариант 15).docx
Скачиваний:
6
Добавлен:
01.09.2024
Размер:
64.01 Кб
Скачать
  1. В решении каких прикладных задач используются алгоритмы определения в графе кратчайших расстояний между заданными вершинами?

1. Маршрутизация в компьютерных сетях: Алгоритмы определения кратчайших путей используются в сетевых протоколах, таких как OSPF (Open Shortest Path First) и IS-IS (Intermediate System to Intermediate System), для определения оптимальных маршрутов между сетевыми узлами.

2. Транспортная логистика: В логистике алгоритмы определения кратчайших путей используются для оптимизации маршрутов доставки грузов и определения оптимальных траекторий для транспортных средств.

3. Геоинформационные системы (ГИС): В ГИС алгоритмы определения кратчайших путей применяются для построения оптимальных маршрутов для навигации, планирования городского транспорта, анализа транспортной доступности и других задач.

4. Социальные сети: В социальных сетях алгоритмы определения кратчайших путей используются для поиска кратчайших связей между пользователями, оптимизации потока информации и рекламных кампаний.

5. Телекоммуникации: В телекоммуникационной отрасли алгоритмы определения кратчайших путей применяются для оптимизации маршрутизации вызовов, передачи данных и управления сетью.

  1. Может ли быть применен рассмотренный алгоритм Дейкстры при определении кратчайшего расстояния в ориентированном графе?

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

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

  1. Как работает алгоритм Дейкстры?

Сначала выбираем путь до начальной вершины равным нулю, и заносим эту вершину во множество уже выбранных, расстояние от которых до оставшихся невыбранных вершин определено. На каждом следующем этапе находим невыбранную вершину, расстояние до которой

наименьшее, соединенную ребром с какой-нибудь вершиной из множества выбранных (это расстояние будет равно расстоянию до уже выбранной вершины плюс длина ребра).

  1. Как работает алгоритм динамического программирования в задачах определения в графе кратчайших расстояний между вершинами?

Метод рассматривает многостадийные процессы принятия решения. При постановке задачи динамического программирования формируется некоторый критерий. Процесс разбивается на стадии (шаги),в которых принимаются решения, приводящие к достижению общей цели. Таким образом, метод динамического программирования - метод

пошаговой оптимизации.

Введем функцию fi, определяющую минимальную длину пути из

начальной вершины в вершину i. Обозначим через Si j длину пути между вершинами i и j, а fj - наименьшую длину пути между вершиной j и

начальной вершиной. Выбирая в качестве i такую вершину, которая минимизирует сумму (Si j + fj), получаем уравнение:

fi = min {Si j + fj}.

Трудность решения данного уравнения заключается в том, что

неизвестная функция входит в обе части равенства. В такой ситуации

приходится прибегать к классическому методу последовательных приближений (итераций), используя рекуррентную формулу:

fi(k+1) = min {Si j + fj(k)},

где fj(k) - k-е приближение функции.

Возможен другой подход к решению поставленной задачи с помощью метода стратегий. При движении из начальной точки i в конечную

k получается приближение fi(0) = Sik, где Sik - длина пути между точками i

и k. Следующее приближение - поиск решения в классе двухзвенных

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

Код на C++:

#include <iostream>

#include <vector>

#include <climits>

#include <ctime>

#include <stack>

using namespace std;

//структура для представления ребра графа

struct Edge {

int target;

int weight;

Edge(int tgt, int w) : target(tgt), weight(w) {}

};

int findShortestPath(vector<vector<Edge>>& graph, int start, int end) {

int n = graph.size();

vector<int> dist(n, INT_MAX); //создание массива для хранения длин путей

dist[start] = 0; //начальная вершина имеет расстояние 0

vector<int> pred(n, -1); // Массив для хранения предшественников вершин в кратчайшем пути

for (int i = 0; i < 2; i++) {

//cout << "" << endl;

//cout << i << ":" << endl;

for (int u = 0; u < n; u++) {

//cout << u << ":" << endl;

for (Edge& e : graph[u]) {

int v = e.target;

int weight = e.weight;

//cout << v << ":" << weight <<endl;

if (dist[u] != INT_MAX && dist[u] + weight < dist[v]) {

dist[v] = dist[u] + weight;

pred[v] = u;

//cout << "YES:" << dist[v] << endl;

}

}

}

}

for (int i = 0; i < n; i++){

cout << "f" << i + 1 << ": " << dist[i] << endl;

}

cout << "Путь: ";

stack<int> path;

int current = end;

while (current != -1) {

path.push(current);

current = pred[current];

}

while (!path.empty()) {

cout << path.top() + 1 << " ";

path.pop();

}

cout << endl;

return dist[end]; //возврат длины кратчайшего пути до конечной вершины

}

int main() {

int n = 7; //количество вершин в графе

vector<vector<Edge>> graph(n);

//добавление рёбер в граф

graph[0].push_back(Edge(1, 1));

graph[0].push_back(Edge(6, 20));

graph[0].push_back(Edge(4, 25));

graph[0].push_back(Edge(3, 8));

graph[1].push_back(Edge(2, 2));

graph[1].push_back(Edge(6, 15));

graph[2].push_back(Edge(5, 3));

graph[3].push_back(Edge(4, 9));

graph[4].push_back(Edge(6, 6));

graph[5].push_back(Edge(6, 4));

/*

graph[0].push_back(Edge(1, 3));

graph[0].push_back(Edge(2, 8));

graph[0].push_back(Edge(3, 4));

graph[1].push_back(Edge(5, 6));

graph[1].push_back(Edge(2, 4));

graph[2].push_back(Edge(5, 6));

graph[2].push_back(Edge(6, 8));

graph[2].push_back(Edge(4, 7));

graph[3].push_back(Edge(2, 10));

graph[3].push_back(Edge(4, 9));

graph[4].push_back(Edge(6, 2));

graph[5].push_back(Edge(6, 4));

*/

/*

graph[0].push_back(Edge(1, 6));

graph[0].push_back(Edge(4, 9));

graph[0].push_back(Edge(3, 7));

graph[1].push_back(Edge(5, 2));

graph[1].push_back(Edge(2, 5));

graph[2].push_back(Edge(3, 2));

graph[2].push_back(Edge(6, 3));

graph[3].push_back(Edge(6, 1));

graph[4].push_back(Edge(5, 4));

graph[4].push_back(Edge(6, 8));

graph[5].push_back(Edge(6, 4));

*/

int start = 1; //начальная вершина

int end = 7; //конечная вершина

start--;

end--;

clock_t startT = clock();

int shortestPath = findShortestPath(graph, start, end);

clock_t endT = clock();

if (shortestPath == INT_MAX){

cout << "Пути между вершинами не существует" << endl;

}

else{

cout << "Кратчайший путь от вершины " << start + 1 << " до вершины " << end + 1 << " равен " << shortestPath << endl;

}

double timeN = double(endT - startT) / CLOCKS_PER_SEC;

cout << "Время решения задачи: " << timeN << " секунд" << endl << endl;

return 0;

}