С Новым годом! Форум программистов, компьютерный форум, киберфорум
Алгоритмы
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.73/37: Рейтинг темы: голосов - 37, средняя оценка - 4.73
 Аватар для VladSharikov
25 / 25 / 7
Регистрация: 02.12.2010
Сообщений: 824

Алгоритм Дейкстры - нахождение кратчайшего маршрута до каждой вершины

02.12.2013, 03:14. Показов 7150. Ответов 37
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Привет.

Понятно как находить кратчайший путь до каждой вершины из заданной. Непонятно как проложить маршрут.
Например, вот статья : http://habrahabr.ru/post/111361/

Там сказано, что есть вектор P, который изначально равен 1 (все значения - их столько, сколько вершин - равны единице). Если вдруг у нас измениться метка вершины на меньшую (то есть появился путь короче предыдущего), то число вектора, которое отвечает за эту вершину измениться на номер текущей вершины. Например, есть вершина 5 - ее метка 10, а теперь появился путь через 4 вершину - метка стала 7. 4 запишется на 5 место в векторе.
Правильно?

Дак вот это не работает (или я что-то не понимаю), если у нас путь до вершины минимальный проходит более чем через одну вершину, как в моем случае.
Матрица:
Вот матрица:
0 3 0 0 7 0 0 0 0
3 0 4 9 0 0 0 0 0
0 4 0 0 0 2 8 0 0
0 9 0 0 0 7 0 0 4
7 0 0 0 0 0 1 0 0
0 0 2 7 0 0 1 7 0
0 0 8 0 1 1 0 2 0
0 0 0 0 0 7 2 0 0
0 0 0 4 0 0 0 0 0

Или граф:
http://habr.habrastorage.org/c... a80979.jpg

Наикратчайший маршрут из 7 из 9 такой: 7->6->4->9. Делая как предлагает автор, я получил вектор P = {1,1,6,1,1,1,1,1,4}. Из этого следует, что в 3 вершину путь такой: 7 -> 6 -> 3 — правильно. Но в 9 такой: 7 -> 4 -> 9. Это неправильно. Я что-то не так сделал?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
02.12.2013, 03:14
Ответы с готовыми решениями:

Алгоритм Дейкстры, нахождение кратчайшего пути
Доброго времени суток всем! У меня вопрос. Написала программку для нахождения кратчайшего пути (алгоритм Дейкстра), но мне надо её как то...

Алгоритм Дейкстры (нахождение кратчайшего пути)
Можно как то еще оптимизировать процедуру в плане скорости? или это предел для чистого QB? SUB ROUTE (S AS INTEGER, F AS INTEGER) ...

Нахождение кратчайшего пути в графе (алгоритм Дейкстры)
Здравствуйте, помогите пожалуйста, СРОЧНО,написать псевдокод реализации нахождения кратчайшего пути в графе на языке СИ. Ввод производиться...

37
 Аватар для Buckstabue
179 / 127 / 25
Регистрация: 12.01.2012
Сообщений: 623
03.12.2013, 03:42
Ох, не знаю, не знаю что здесь такого сложного. Могу поделиться программой, которая ищет длину наикратчайшего пути до конкретно заданной вершины, построенной для этой задачи: http://acmp.ru/index.asp?main=task&id_task=132 . Тебе небольшое задание: либо свою с нуля записать, либо просто модифицируй цикл так, чтобы он заканчивал свое дело только тогда, когда будут помечены все вершины графа.
Ну а про алгоритм восстановления пути расскажу, что помню из универа: пусть нам дана вершина A и B, и расстояние между ними. Тогда строим путь из B к A следующим образом: смотрим всю окрестность вершины B(множество вершин, смежных B), выбираем ту вершину, расстояние до которой из A наименьшее, если таких вершин несколько, то выбираем любую(назовем ее C), включаем ее в путь. Далее опять, изучаем окрестность вершины C, снова выбираем ту вершину, расстояние до которой из А наименьшее, включаем ее в путь. В конце концов мы рано или поздно придем к вершине А и восстановим путь. Может не самое быстрое решение, но реально работющее
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <fstream>
 
typedef unsigned short ushort;
 
/*template <class T>
void printArray(T *arr, int N);
 
*/
int main()
{
    std::ifstream fin("input.txt");
    std::ofstream fout;
    ushort *marks = NULL; // массив маркировок вершин графа
    ushort *permanentMarks = NULL; // массив наличия постоянной марки
    short **adjacencyMatrix = NULL; // матрица смежности
    short p; // число вершин графа
    short S; // номер вершины отправления
    short curS; // текущая вершина
    short F; // номер вершины завершения пути
 
    fin >> p >> S >> F;
    --S;
    --F;
    // выделение памяти  и инициализация матрицы смежности графа
    marks = new ushort[p];
    permanentMarks = new ushort[p];
    memset(marks, 0xFF, sizeof (*marks) * p);
    memset(permanentMarks, 0, sizeof (*permanentMarks) * p);
    adjacencyMatrix = new short*[p];
    for (int i = 0; i < p; ++i)
    {
        adjacencyMatrix[i] = new short[p];
        for (int j = 0; j < p; ++j)
            fin >> adjacencyMatrix[i][j];
    }
    fin.close();
 
    permanentMarks[S] = 1;
    marks[S] = 0;
    curS = S;
    while (!permanentMarks[F]) // пока не помечен конец пути
    {
        for (int j = 0; j < p; ++j)
        {
            if (adjacencyMatrix[curS][j] != -1 && !permanentMarks[j]
                && (marks[curS] + adjacencyMatrix[curS][j]) < marks[j])
            {
                marks[j] = marks[curS] + adjacencyMatrix[curS][j];
            }
        }
        // поиск минимальной непомеченной метки
 
        /* вначале ищем любую непомеченную вершину */
        for (int i = 0; i < p; ++i)
        {
            if (!permanentMarks[i])
            {
                curS = i;
                break;
            }
        }
        for (int i = curS + 1; i < p; ++i)
        {
            if (!permanentMarks[i] && marks[i] < marks[curS])
                curS = i;
        }
        permanentMarks[curS] = 1;
        /*
        std::cout << "Marks:\n";
        printArray(marks, p);
        std::cout << "-----------------\n";
        std::cout << "PermanentMarks:\n";
        printArray(permanentMarks, p);
        std::cout << "*******************\n";*/
    }
 
    /*std::cout << marks[F];*/
    fout.open("output.txt");
    if (marks[F] == USHRT_MAX)
        fout << -1;
    else
        fout << marks[F];
    fout.close();
 
    delete[] marks;
    delete[] permanentMarks;
    for (int i = p -1; i >= 0; --i)
        delete[] adjacencyMatrix[i];
    delete[] adjacencyMatrix;
 
    return 0;
}
/*
template <class T>
void printArray(T *arr, int N)
{
    for (int i = 0; i < N; ++i)
    {
        std::cout << std::setw(6) << i << ' ';
    }
    std::cout << std::endl;
    for (int i = 0; i < N; ++i)
    {
        std::cout << std::setw(6) << arr[i] << ' ';
    }
    std::cout << std::endl;
}*/
1
835 / 643 / 101
Регистрация: 20.08.2013
Сообщений: 2,524
03.12.2013, 13:54
Цитата Сообщение от Buckstabue Посмотреть сообщение
Ну а про алгоритм восстановления пути расскажу, что помню из универа: пусть нам дана вершина A и B, и расстояние между ними. Тогда строим путь из B к A следующим образом: смотрим всю окрестность вершины B(множество вершин, смежных B), выбираем ту вершину, расстояние до которой из A наименьшее, если таких вершин несколько, то выбираем любую(назовем ее C), включаем ее в путь. Далее опять, изучаем окрестность вершины C, снова выбираем ту вершину, расстояние до которой из А наименьшее, включаем ее в путь. В конце концов мы рано или поздно придем к вершине А и восстановим путь. Может не самое быстрое решение, но реально работющее
Что-то по-моему не работающее оно вовсе...
1
294 / 265 / 48
Регистрация: 09.04.2013
Сообщений: 1,038
03.12.2013, 15:40
Да вы, батенька, почти некропостер.

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

P.S. Помню, в универе, преподаватель давал этот алгоритм в виде кода на паскале, но не объяснил его суть так же доходчиво как в статье, поскольку такой алгоритм мне был без надобности все это время, то я до сих пор думал что пусть это и самый быстрый алгоритм, но и самый трудный в понимании. Или, может, преподаватель рассматривал немного другой вариант алгоритма.
1
 Аватар для VladSharikov
25 / 25 / 7
Регистрация: 02.12.2010
Сообщений: 824
03.12.2013, 16:22  [ТС]
wingblack, точно, неправильно инициализировал.
Но суть не поменялась. Теперь он равен 7 7 6 7 7 7 7 7 9. Тоже самое, но с 7. Может я вообще не понимаю как его строить, проясните.

Пс: а что такое некропостер? Старые посты читаю?
0
294 / 265 / 48
Регистрация: 09.04.2013
Сообщений: 1,038
03.12.2013, 19:20
Цитата Сообщение от VladSharikov Посмотреть сообщение
Пс: а что такое некропостер? Старые посты читаю?
"necro" -мертвое
"post" - в данном случае "оставлять сообщение"
чаще всего употребляется когда кто-то пишет в тему форума многолетней давности.

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

Добавлено через 4 минуты
Может напишешь как ты решаешь и выложишь куда-нить ?
Не код проги конечно

Добавлено через 2 часа 16 минут
Вот я попробовал реализовать на той картинке
1
 Аватар для VladSharikov
25 / 25 / 7
Регистрация: 02.12.2010
Сообщений: 824
03.12.2013, 20:35  [ТС]
wingblack,
во-первых, спасибо за ответы в любом случае!
во-вторых, по крайней мере длины путей получились у меня и у вас такие же. я не очень понимаю, как изменяется по ходу дела у вас вектор P.

Из статьи:
Далее на этапе пересчета значения метки для рассматриваемой вершины, в случае если метка рассматриваемой вершины меняется на меньшую, в массив Р мы записываем значение текущей вершины W.
Я понял это так. На одном из этапов, например при рассмотрении 4 вершины (из моего примера), мы мы изменили метку 9 вершины с 13 на 12, то есть произошло изменение метки вершины.

Раньше я делал так.

Сейчас можно написать add:

Пока писал пост понял, что нужно запоминать текущую вершину с при изменении метки бесконечности на число, а не только с числа на число.

P.S.: в то как вы делали не сильно пока вдумался, только зашел домой, сейчас попробую сам еще раз пересчитать.

еще раз спасибо большое за ответы, вы очень помогаете

Добавлено через 21 минуту
Так стоп
смотрю сейчас на то, что сделали вы и нифига не понимаю.

поясните как и почему изменяются значения вектора P.
На 4 картинке у вас стоит цифра 8, хотя через 8 вообще не надо проходить, чтобы попасть в 4 кратчайшим путем. Может я не так понимаю смысл вектора P?

Объясните по какому принципу изменяется вектор P. И смысл этих изменений. И что должно быть на выходе, как это нужно понять будет.
Спасибо.

p.s.: кода пока что и нет. пока решаю на бумаге, позже буду преобразовывать это все в код.
0
294 / 265 / 48
Регистрация: 09.04.2013
Сообщений: 1,038
03.12.2013, 22:18
Я могу где-то ошибаться, если что.
Была мысль потратить лишние полчасика и показать наглядно если у тебя есть микрофон чтобы общаться в прямом эфире. Если есть такая возможность - кинь контакт в личку, поддерживается skype, hangout, *вставить_свое* или можно через joinme
1
 Аватар для VladSharikov
25 / 25 / 7
Регистрация: 02.12.2010
Сообщений: 824
03.12.2013, 23:22  [ТС]
Спасибо) прямо сто пятьсот миллионов плюсов)

осталось выдумать как это все закодить)))
0
294 / 265 / 48
Регистрация: 09.04.2013
Сообщений: 1,038
04.12.2013, 00:23
А что выдумывать, берешь готовую реализацию алгоритма на нужном ЯП и кодишь.
1
 Аватар для VladSharikov
25 / 25 / 7
Регистрация: 02.12.2010
Сообщений: 824
04.12.2013, 00:51  [ТС]
wingblack,
например?

готовой толковой пока не нашел.

мне нужно на delphi, но пойдет на любом яп) одна фигня
0
 Аватар для Buckstabue
179 / 127 / 25
Регистрация: 12.01.2012
Сообщений: 623
04.12.2013, 03:37
Qwertiy, почему это неработающий? Можете привести контр-пример?

Добавлено через 1 час 35 минут
Вообще, мой алгоритм восстановления пути правилен, но для удобства требует матрицу инцидентности, а не матрицу смежности. Впрочем, если граф неориентирован, то сойдет и матрица смежности

Добавлено через 28 минут
Ну и кто говорил, что мой алгоритм нерабочий? Сейчас проверил, все работает
Код:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#include <fstream>
#include <iostream>
#include <iomanip>
#include <climits>
#include <cstring>
#include <list>
 
typedef unsigned short ushort;
 
int getIndexOfVertexWithMinimalDistance(const short * adjancedRow,
                                        const int vertices,
                                        const ushort * marks);
template <class T>
void printArray(T *arr, int N);
 
int main()
{
    std::ifstream fin("input.txt");
    std::ofstream fout;
    ushort *marks = NULL; // массив маркировок вершин графа
    ushort *permanentMarks = NULL; // массив наличия постоянной марки
    short **adjacencyMatrix = NULL; // матрица смежности
    short verticesNum; // число вершин графа
    short startVertexIndex; // номер вершины отправления
    short curVertexIndex; // текущая вершина
    short endVertexIndex; // номер вершины завершения пути
    std::list<int> shortestPath;
 
    fin >> verticesNum >> startVertexIndex >> endVertexIndex;
    --startVertexIndex;
    --endVertexIndex;
    // выделение памяти  и инициализация матрицы смежности графа
    marks = new ushort[verticesNum];
    permanentMarks = new ushort[verticesNum];
    memset(marks, 0xFF, sizeof (*marks) * verticesNum);
    memset(permanentMarks, 0, sizeof (*permanentMarks) * verticesNum);
    adjacencyMatrix = new short*[verticesNum];
    for (int i = 0; i < verticesNum; ++i)
    {
        adjacencyMatrix[i] = new short[verticesNum];
        for (int j = 0; j < verticesNum; ++j)
        {
            int val;
 
            fin >> val;
            if (val == 0)
            {
                val = -1;
            }
 
            adjacencyMatrix[i][j] = val;
        }
    }
    fin.close();
 
    permanentMarks[startVertexIndex] = 1;
    marks[startVertexIndex] = 0;
    curVertexIndex = startVertexIndex;
    while (!permanentMarks[endVertexIndex]) // пока не помечен конец пути
    {
        for (int j = 0; j < verticesNum; ++j)
        {
            if (adjacencyMatrix[curVertexIndex][j] != -1 && !permanentMarks[j]
                && (marks[curVertexIndex] + adjacencyMatrix[curVertexIndex][j]) < marks[j])
            {
                marks[j] = marks[curVertexIndex] + adjacencyMatrix[curVertexIndex][j];
            }
        }
        // поиск минимальной непомеченной метки
 
        /* вначале ищем любую непомеченную вершину */
        for (int i = 0; i < verticesNum; ++i)
        {
            if (!permanentMarks[i])
            {
                curVertexIndex = i;
                break;
            }
        }
        for (int i = curVertexIndex + 1; i < verticesNum; ++i)
        {
            if (!permanentMarks[i] && marks[i] < marks[curVertexIndex])
                curVertexIndex = i;
        }
        permanentMarks[curVertexIndex] = 1;
        /*
        std::cout << "Marks:\n";
        printArray(marks, p);
        std::cout << "-----------------\n";
        std::cout << "PermanentMarks:\n";
        printArray(permanentMarks, p);
        std::cout << "*******************\n";*/
    }
 
    /*std::cout << marks[F];*/
    fout.open("output.txt");
    if (marks[endVertexIndex] == USHRT_MAX)
    {
        fout << -1;
    }
    else
    {
        fout << marks[endVertexIndex] << std::endl;
 
        std::cout << "Marks:\n";
        printArray(marks, verticesNum);
        std::cout << "-----------------\n";
        std::cout << "PermanentMarks:\n";
        printArray(permanentMarks, verticesNum);
        std::cout << "*******************\n";
 
 
        curVertexIndex = endVertexIndex;
        shortestPath.push_front(curVertexIndex + 1);
 
        while (curVertexIndex != startVertexIndex)
        {
            std::cout << "currentRow:\n";
            printArray(adjacencyMatrix[curVertexIndex], verticesNum);
            std::cout << "****************" << std::endl;
 
            curVertexIndex =
               getIndexOfVertexWithMinimalDistance(adjacencyMatrix[curVertexIndex],
                                                   verticesNum,
                                                   marks);
 
            shortestPath.push_front(curVertexIndex + 1);
        }
 
        for (std::list<int>::iterator it = shortestPath.begin();
             it != shortestPath.end(); ++it)
        {
            fout << *it << " -> ";
        }
    }
    fout.close();
 
    delete[] marks;
    delete[] permanentMarks;
    for (int i = verticesNum -1; i >= 0; --i)
    {
        delete[] adjacencyMatrix[i];
    }
    delete[] adjacencyMatrix;
 
    return 0;
}
 
int getIndexOfVertexWithMinimalDistance(const short * adjancedRow,
                                        const int vertices,
                                        const ushort * marks)
{
    int minIndex;
 
    // поиск индекса первого положительного числа
    for (minIndex = 0; adjancedRow[minIndex] <= 0; ++minIndex);
    // поиск индекса минимального положительного числа
    for (int i = 1; i < vertices; ++i)
    {
        if (adjancedRow[i] < adjancedRow[minIndex] && adjancedRow[i] > 0 &&
                marks[i] < marks[minIndex])
        {
            minIndex = i;
        }
    }
 
    return minIndex;
}
 
template <class T>
void printArray(T *arr, int N)
{
    for (int i = 0; i < N; ++i)
    {
        std::cout << std::setw(6) << i << ' ';
    }
    std::cout << std::endl;
    for (int i = 0; i < N; ++i)
    {
        std::cout << std::setw(6) << arr[i] << ' ';
    }
    std::cout << std::endl;
}

Входный данные:
Кликните здесь для просмотра всего текста
9 7 9
0 3 0 0 7 0 0 0 0
3 0 4 9 0 0 0 0 0
0 4 0 0 0 2 8 0 0
0 9 0 0 0 7 0 0 4
7 0 0 0 0 0 1 0 0
0 0 2 7 0 0 1 7 0
0 0 8 0 1 1 0 2 0
0 0 0 0 0 7 2 0 0
0 0 0 4 0 0 0 0 0
1
294 / 265 / 48
Регистрация: 09.04.2013
Сообщений: 1,038
04.12.2013, 08:52
Цитата Сообщение от VladSharikov Посмотреть сообщение
wingblack,
например?
готовой толковой пока не нашел.
мне нужно на delphi, но пойдет на любом яп) одна фигня
На форуме, очевидно, вопрос про Дейкстру вставал неоднократно.

http://www.delphisources.ru/pa... oritm.html
http://e-maxx.ru/algo/dijkstra
http://kvodo.ru/dijkstra-algorithm.html

Кстати, на Википедии сейчас увидел вполне наглядное описание алгоритма в картинках.
1
835 / 643 / 101
Регистрация: 20.08.2013
Сообщений: 2,524
04.12.2013, 15:27
Цитата Сообщение от Buckstabue Посмотреть сообщение
Можете привести контр-пример?
Запросто:
Code
1
2
3
4
5
4 1 4
0 3 4 0
3 0 3 4
4 3 0 1
0 4 1 0
Результат:
Code
1
2
5
1 -> 2 -> 4 ->
Ответ 5 верный, но путь 1 -> 2 -> 4 имеет стоимость 7.
2
 Аватар для Buckstabue
179 / 127 / 25
Регистрация: 12.01.2012
Сообщений: 623
05.12.2013, 00:18
Признаюсь, лажанулся. Совсем забыл это правило. Сейчас попробую восстановить. Так-то звучит оно так(Этап 2):
http://imghost.in/img/2013-12/... xzl8gy.jpg

Добавлено через 18 минут
Вот новая редакция:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#include <fstream>
#include <iostream>
#include <iomanip>
#include <climits>
#include <cstring>
#include <list>
 
typedef unsigned short ushort;
 
int getIndexOfVertexWithMinimalDistance(const short * adjancedRow,
                                        const int vertices,
                                        const ushort * marks,
                                        int curVertexIndex);
template <class T>
void printArray(T *arr, int N);
 
int main()
{
    std::ifstream fin("input.txt");
    std::ofstream fout;
    ushort *marks = NULL; // массив маркировок вершин графа
    ushort *permanentMarks = NULL; // массив наличия постоянной марки
    short **adjacencyMatrix = NULL; // матрица смежности
    short verticesNum; // число вершин графа
    short startVertexIndex; // номер вершины отправления
    short curVertexIndex; // текущая вершина
    short endVertexIndex; // номер вершины завершения пути
    std::list<int> shortestPath;
 
    fin >> verticesNum >> startVertexIndex >> endVertexIndex;
    --startVertexIndex;
    --endVertexIndex;
    // выделение памяти  и инициализация матрицы смежности графа
    marks = new ushort[verticesNum];
    permanentMarks = new ushort[verticesNum];
    memset(marks, 0xFF, sizeof (*marks) * verticesNum);
    memset(permanentMarks, 0, sizeof (*permanentMarks) * verticesNum);
    adjacencyMatrix = new short*[verticesNum];
    for (int i = 0; i < verticesNum; ++i)
    {
        adjacencyMatrix[i] = new short[verticesNum];
        for (int j = 0; j < verticesNum; ++j)
        {
            int val;
 
            fin >> val;
            if (val == 0)
            {
                val = -1;
            }
 
            adjacencyMatrix[i][j] = val;
        }
    }
    fin.close();
 
    permanentMarks[startVertexIndex] = 1;
    marks[startVertexIndex] = 0;
    curVertexIndex = startVertexIndex;
    while (!permanentMarks[endVertexIndex]) // пока не помечен конец пути
    {
        for (int j = 0; j < verticesNum; ++j)
        {
            if (adjacencyMatrix[curVertexIndex][j] != -1 && !permanentMarks[j]
                && (marks[curVertexIndex] + adjacencyMatrix[curVertexIndex][j]) < marks[j])
            {
                marks[j] = marks[curVertexIndex] + adjacencyMatrix[curVertexIndex][j];
            }
        }
        // поиск минимальной непомеченной метки
 
        /* вначале ищем любую непомеченную вершину */
        for (int i = 0; i < verticesNum; ++i)
        {
            if (!permanentMarks[i])
            {
                curVertexIndex = i;
                break;
            }
        }
        for (int i = curVertexIndex + 1; i < verticesNum; ++i)
        {
            if (!permanentMarks[i] && marks[i] < marks[curVertexIndex])
                curVertexIndex = i;
        }
        permanentMarks[curVertexIndex] = 1;
        /*
        std::cout << "Marks:\n";
        printArray(marks, p);
        std::cout << "-----------------\n";
        std::cout << "PermanentMarks:\n";
        printArray(permanentMarks, p);
        std::cout << "*******************\n";*/
    }
 
    /*std::cout << marks[F];*/
    fout.open("output.txt");
    if (marks[endVertexIndex] == USHRT_MAX)
    {
        fout << -1;
    }
    else
    {
        fout << marks[endVertexIndex] << std::endl;
 
        std::cout << "Marks:\n";
        printArray(marks, verticesNum);
        std::cout << "-----------------\n";
//        std::cout << "PermanentMarks:\n";
//        printArray(permanentMarks, verticesNum);
//        std::cout << "*******************\n";
 
 
        curVertexIndex = endVertexIndex;
        shortestPath.push_front(curVertexIndex + 1);
 
        while (curVertexIndex != startVertexIndex)
        {
            std::cout << "currentRow:\n";
            printArray(adjacencyMatrix[curVertexIndex], verticesNum);
            std::cout << "****************" << std::endl;
 
            curVertexIndex =
               getIndexOfVertexWithMinimalDistance(adjacencyMatrix[curVertexIndex],
                                                   verticesNum,
                                                   marks,
                                                   curVertexIndex);
 
            shortestPath.push_front(curVertexIndex + 1);
        }
 
        for (std::list<int>::iterator it = shortestPath.begin();
             it != shortestPath.end(); ++it)
        {
            fout << *it << " -> ";
        }
    }
    fout.close();
 
    delete[] marks;
    delete[] permanentMarks;
    for (int i = verticesNum -1; i >= 0; --i)
    {
        delete[] adjacencyMatrix[i];
    }
    delete[] adjacencyMatrix;
 
    return 0;
}
 
int getIndexOfVertexWithMinimalDistance(const short * adjancedRow,
                                        const int vertices,
                                        const ushort * marks,
                                        int curVertexIndex)
{
    short curDistance = marks[curVertexIndex];
 
    // поиск индекса минимального положительного числа
    for (int i = 0; i < vertices; ++i)
    {
        if (adjancedRow[i] > 0 && (marks[i] + adjancedRow[i] == curDistance))
        {
            return i;
        }
    }
 
    return -1;
}
 
template <class T>
void printArray(T *arr, int N)
{
    for (int i = 0; i < N; ++i)
    {
        std::cout << std::setw(6) << i << ' ';
    }
    std::cout << std::endl;
    for (int i = 0; i < N; ++i)
    {
        std::cout << std::setw(6) << arr[i] << ' ';
    }
    std::cout << std::endl;
}
1
1966 / 822 / 114
Регистрация: 01.10.2012
Сообщений: 4,788
Записей в блоге: 2
05.12.2013, 12:01
Давно, когда был студентом (и когда ничего не слышали об интернете), придумал свой алгоритм нахождения пути в графе. Скорее всего этот велосипед хорошо известен, а может тот самый Дейкстра и есть. Зацените:

- от весов всех ребер из исходной вершины отнимаем минимальное. В результате вес хотя бы 1 ребра будет 0. Напр http://habr.habrastorage.org/c... a80979.jpg после первого шага 2 ребра обнулились и имеем 3 вершины R5, R6, R7. Теперь оптимальные пути в эти вершины найдены, и все они становятся "началами"

- повторяем процедуру (теперь берем все ребра из R5, R6, R7) пока это возможно. Ну вот и все, пути готовы. Вывод на печать - когда ребро "обнулилось" запоминаем в нем источник (а тот знает предыдущий)

Да, когда читал книги (уже и не помню какие) запомнилось выражение "каждый участок оптимального пути является оптимальным"
0
835 / 643 / 101
Регистрация: 20.08.2013
Сообщений: 2,524
05.12.2013, 13:12
Цитата Сообщение от Igor3D Посмотреть сообщение
Скорее всего этот велосипед хорошо известен
Ага, по сути bfs, но вместо очереди использовать нечто отсортированное по суммарной длине пути в эту вершину.

Цитата Сообщение от Igor3D Посмотреть сообщение
запомнилось выражение "каждый участок оптимального пути является оптимальным"
Обычно оно верно. Но могут быть случаи, когда под кратчайшим путём понимается не сумма весов, а некоторая другая функция, - тогда оно может и не соблюдаться. Например, если в качестве стоимости пути брать максимальную из стоимостей проходимых рёбер.
1
 Аватар для VladSharikov
25 / 25 / 7
Регистрация: 02.12.2010
Сообщений: 824
10.12.2013, 18:22  [ТС]
Buckstabue,

пришло время писать сам алгоритм, я ведь могу опираться на ваш алгоритм?)) Использовать его могу?

Читаю и что-то даже понимаю По-крайней мере, понимаю что для чего нужно. В суть пока смутно вник, но представляю)

Buckstabue, скажите, вот эта часть:
Цитата Сообщение от Qwertiy Посмотреть сообщение
4 1 4
означает, что всего у нас 4 вершины и маршрут мы ищем из 1 в 4, правильно?

Алгоритм нужно доработать вы говорили. Вот это и нужно было доработать, правильно?

Добавлено через 22 часа 18 минут
Кстати, появилось еще несколько вопросов.

Можно ли алгоритм найти минимальный путь на графе если из вершины А в вершину Б может быть не один путь, а не сколько? в смысле "ребро" не одно, а несколько.

Препод сказал, что нужно обязательно в пути указывать название ребра, которое нужно пройти, чтобы добраться из одной вершины в другую.
например, для моего графа (http://habr.habrastorage.org/c... a80979.jpg) нужно записать путь не R1-R2-R3, а такой: R1-A-R2-H-R3. Это нормуль? По-моему, просто лишние телодвижения нужно осуществлять.
0
835 / 643 / 101
Регистрация: 20.08.2013
Сообщений: 2,524
10.12.2013, 18:28
Цитата Сообщение от VladSharikov Посмотреть сообщение
означает, что всего у нас 4 вершины и маршрут мы ищем из 1 в 4, правильно?
Да.

Цитата Сообщение от VladSharikov Посмотреть сообщение
Вот это и нужно было доработать, правильно?
Вроде бы Buckstabue поправил... Правда я не разбирался.

Цитата Сообщение от VladSharikov Посмотреть сообщение
"ребро" не одно, а несколько.
В матрицу надо включать минимальное.
Очевидно же, что если неминимальное ребро заменить минимальным, то путь уменьшится.
А если вдруг увеличится (ну можно выбрать какой-нибудь хитрый способ подсчёта длины пути), то дейкстра в принципе не применим.

Цитата Сообщение от VladSharikov Посмотреть сообщение
репод сказал, что нужно обязательно в пути указывать название ребра, которое нужно пройти, чтобы добраться из одной вершины в другую.
Если есть кратные рёбра, то да.

Цитата Сообщение от VladSharikov Посмотреть сообщение
По-моему, просто лишние телодвижения нужно осуществлять.
Рёбра выбираются однозначно исходя из их веса, поэтому такую матрицу надо построить заранее, а потом просто из неё вывести имена.

Цитата Сообщение от VladSharikov Посмотреть сообщение
пришло время писать сам алгоритм
У тебя же был алгоритм. Что вдруг перестал устраивать?
1
 Аватар для VladSharikov
25 / 25 / 7
Регистрация: 02.12.2010
Сообщений: 824
10.12.2013, 20:00  [ТС]
Цитата Сообщение от Qwertiy Посмотреть сообщение
Рёбра выбираются однозначно исходя из их веса, поэтому такую матрицу надо построить заранее, а потом просто из неё вывести имена.
Только что подумал: а в чем проблема создать вторую матрицу, где будут на местах весов имена ребер? Ты об этом?

Цитата Сообщение от Qwertiy Посмотреть сообщение
Если есть кратные рёбра, то да.
Какие? Кратные - это такие, что конечные и начальные вершины одни и те же? То есть два ребра из одного ребра в другое? Два или больше. Дак если мы в матрицу включим минимальное, то и в матрицу имен мы включим название минимального ребра - раз. А во-вторых, у нас ведь в принципе будет одно ребро, не будет кратных. Чего я не понял?

Цитата Сообщение от Qwertiy Посмотреть сообщение
Вроде бы Buckstabue поправил... Правда я не разбирался.
Дак интересно свое написать, опираясь на другой алгоритм, а не просто списать.

В любом случае, благодарю за ответ!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
10.12.2013, 20:00
Помогаю со студенческими работами здесь

Нахождение кратчайшего пути между заданными городами (алгоритм Дейкстры)
Народ, подскажите пожалуйста, на кону допуск к сессии. Чего то я запутался с этими списками. Буду оень признателен. &quot;Разработать...

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

Алгоритм поиска кратчайшего маршрута
Моё почтение всем! Буду ОЧЕНЬ благодарен тому, кто сможет мне помочь найти алгоритм (или исходник на VB )поиска кратчайшего маршрута ...

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

Алгоритм решения задачи по определению кратчайшего маршрута
Как определить кратчайший маршрут, проходящий через все населенные пункты? &quot;В лоб&quot; не хочется, а как &quot;цивилизовано&quot;? Начал...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути
Programma_Boinc 01.01.2026
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути Сочетание глобально распределённой вычислительной мощности и инновационных. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru