Форум программистов, компьютерный форум, киберфорум
Pascal (Паскаль)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.65/48: Рейтинг темы: голосов - 48, средняя оценка - 4.65
1 / 1 / 0
Регистрация: 05.09.2014
Сообщений: 57

Найти кратчайший путь между двумя заданными городами

23.02.2015, 16:58. Показов 9569. Ответов 3
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Дана плоская страна и в ней n городов. Предположим, что в этой стране есть дорожная сеть. Найти кратчайший путь между двумя заданными городами.
должна находить кратчайшие расстояния и выводить маршрут (последовательность прохождения городов).
Как дописать программу, чтобы она выводила маршрут?
Pascal
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
program Project64;
uses
  SysUtils,
  windows;
const
n = 8;
inf = 1000;
var
f: text;
D: array[1..n, 1..n] of integer;
i, j, k, p,min:integer;         //k-начальная вершина   p-счетчик
A,B,C: array[1..n] of integer;
begin
  SetConsoleOutputCP(1251);
  SetConsoleCP(1251);
  Assign(f, 'Алгоритм.txt');
  Reset(f);
    for i:=1 to n do
      for j:=1 to n do
      begin
        read(f, d[i,j]);
        if d[i,j]=-1 then d[i,j]:=inf;  //считали из файла матрицу
      end;
  Close(f);
    for i:=1 to n do
    begin
      for j:=1 to n do
        if d[i,j]=inf then write('-':5)
        else  write(d[i,j]:5);     //напечатали
        writeln;
    end;
  writeln('Введите начальную вершину');
  readln(k);
   for i:=1 to n do
     begin              //заполнили массив
      A[i]:=0;
      b[i]:=D[k,i];
      C[i]:=k;
     end;
   A[k]:=1;
  for p:=1 to n-1 do
    begin
    min:=inf;    //пошёл сам алгоритм
      for i:=1 to n do
        begin
          if (A[i]=0) and (B[i]<min) then
            begin
              min:=B[i];
              j:=i;
            end;
          end;
            A[j]:=1;
          for i:=1 to n do
              if B[i]>B[j]+D[i,j]  then
              begin
                B[i]:=B[j]+D[i,j];
                C[i]:=j;
              end;
        end;
   for i:=1 to n do
   begin
     write(i:6);
     writeln(B[i]:5);
   end;
  readln;
end.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
23.02.2015, 16:58
Ответы с готовыми решениями:

Работа с графом.Найти кратчайший маршрут между двумя вершинами.
Между некоторыми деревнями края Васюки ходят автобусы. Поскольку пассажиропотоки здесь не очень большие, то автобусы ходят всего несколько...

Задача на взвешенный ориентированный граф, существует ли путь L между двумя заданными вершинами
Во входном файле указывается количество вершин взвешенного ориентированного графа и матрица смежности. Определить, существует ли путь...

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

3
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8652 / 4487 / 1669
Регистрация: 01.02.2015
Сообщений: 13,895
Записей в блоге: 12
24.02.2015, 00:38
Если ошибаюсь, пусть меня поправят.
Задачу поиска минимального по затратам пути во взвешенном графе удобно решать методом Флойда-Уоршелла.
Там на основе весовой матрицы создаются две матрицы - матрица достижимостей и матрица путей, по которым и находится путь между двумя произвольными городами.
Если не затруднит, опишите свой алгоритм и структуры данных. Просто алгоритмы без пояснений, в большинстве своём, выглядят как тарабарщина.
Недавно на форуме из любопытства за пару-тройку часов сделал кому-то реализацию Ф-У. Алгоритм несложный. Есть хорошие описания в Wikipedia и на e-maxx.
В моей реализации сделано допущение по исходным данным: в матрице весов приведены веса дуг между вершинами, но если вес дуги равен 0 - прямого пути между данными вершинами нет.
В процедуре алгоритма Ф-У на основании весовой матрицы v создаются матрица достижимости d и матрица путей p. В процедуре RestorePath на основе d и p восстанавливается путь между вершинами A и B.
Это была тестовая программа для отладки алгоритма.
Pascal
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
{Реализация алгоритма Флойда-Уоршелла}
program FloydWarshall;
 
const
  n = 5; {количество вершин графа}
  INFINITY = MaxInt;
type
  TRow = array [0..n - 1] of integer;
  TVertex = array [0..n - 1] of TRow;
const
  Vertex1: TVertex =
    (
    (0, 0, 5, 0, 0),
    (7, 0, 0, 0, 10),
    (0, 7, 0, 0, 0),
    (0, 0, 6, 0, 4),
    (0, 0, 1, 0, 0)
    );
  Vertex2: TVertex =
    (
    (0, 3, 2, 0, 0),
    (0, 0, 0, 4, 0),
    (0, 0, 0, 6, 0),
    (0, 0, 0, 0, 2),
    (0, 0, 0, 0, 0)
    );
 
  procedure FloydWarshall(v: TVertex; n: integer; var d, p: TVertex);
  var
    i, j, k: integer;
  begin
    {
    матрицу веса дуги преобразуем в требуемый для алгоритма вид
    - если i=j, то d[i, j]:=0
    - если из i в j нет ребра, то d[i, j]:=INFINITY (бесконечности)
    - иначе d[i, j] равно весу ребра из i в j
    подготовим матрицу для восстановления пути p
    }
    d := v;
    for i := 0 to pred(n) do
      for j := 0 to pred(n) do
      begin
        if d[i, j] = 0 then
          d[i, j] := INFINITY;
        if i = j then
          d[i, j] := 0;
        p[i, j] := j;
      end;
    for k := 0 to pred(n) do
    begin
      for i := 0 to pred(n) do
      begin
        for j := 0 to pred(n) do
        begin
          if (d[i, k] <> INFINITY) and (d[k, j] <> INFINITY) then
          begin
            if (d[i, j] > d[i, k] + d[k, j]) then
            begin
              d[i, j] := d[i, k] + d[k, j];
              p[i, j] := p[i, k];
            end;
          end;
        end;
      end;
    end;
  end;
 
  procedure RestorePath(const D, P: TVertex; n: integer; A, B: integer);
  var
    k: integer;
  begin
    if A >= n then
    begin
      writeln('The vertex A is out of range.');
      exit;
    end;
    if B >= n then
    begin
      writeln('The vertex B is out of range.');
      exit;
    end;
    if D[A, B] = INFINITY then
    begin
      writeln('There is not a path from vertex ', A, ' to vertex ', B, '.');
      exit;
    end;
    Write('The path from vertex ', A, ' to vertex ', B, ' is: <');
    Write(A: 4);
    k := A;
    while k <> B do
    begin
      k := p[k, B];
      Write(k: 4);
    end;
    writeln('>');
  end;
 
  procedure ShowMatrix(const M: TVertex; n: integer);
  var
    i, j: integer;
  begin
    for i := 0 to pred(n) do
    begin
      for j := 0 to pred(n) do
      begin
        if M[i, j] <> INFINITY then
          Write(M[i, j]: 4)
        else
          Write('inf': 4);
      end;
      writeln;
    end;
  end;
 
  procedure TestAlgoFW(const Vertex: TVertex; n: integer);
  var
    D, P: TVertex;
  begin
    FloydWarshall(Vertex, n, D, P);
    writeln('Vertex matrix:');
    ShowMatrix(Vertex, n);
    writeln('Distance matrix:');
    ShowMatrix(D, n);
    writeln('Path matrix:');
    ShowMatrix(P, n);
    RestorePath(D, P, n, 3, 1);
    RestorePath(D, P, n, 0, 3);
    RestorePath(D, P, n, 3, 3);
  end;
 
begin
  TestAlgoFW(Vertex1, n);
  TestAlgoFW(Vertex2, n);
end.
Ещё есть алгоритм Дейкстры. Он отличается от Ф-У тем, что ищет кратчайшие пути не для всех вершин (городов), а из одного города ко всем остальным.

Если же вам дорог собственный вариант, то поясните, что там происходит.
0
1 / 1 / 0
Регистрация: 05.09.2014
Сообщений: 57
24.02.2015, 07:13  [ТС]
это и есть алгоритм дейкстры
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8652 / 4487 / 1669
Регистрация: 01.02.2015
Сообщений: 13,895
Записей в блоге: 12
24.02.2015, 22:31
А-а-а...
Я ещё его не "проходил".

Добавлено через 13 часов 58 минут
natascha, смотри. Если почитать описания алгоритма Дейкстры, сопоставить с ним переменные в твоём коде, то получается, что в массиве C хранится путь.
После отработки алгоритма у тебя есть заполненные массивы путей C и расстояний B из вершины k до всех остальных вершин. Если нужно вывести путь от k до m нужно воспользоваться стеком.
Pascal
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
procedure ShowPath(A, B: integer; const P, D: array[1..n] of integer);
  var
    Q: array[1..n] of integer;
    Len: integer;
    v: integer;
  begin
    Len := 1;
    if D[B] = INF then
      writeln('There is not exist path from ', A, ' to ', B, '.')
    else
    begin
      v := B;
      repeat
        Q[Len] := v;
        Inc(Len);
        v := P[v];
      until v=-1;
      write('A path from ', A, ' to ', B, ' is <');
      for v := Len - 1 downto 1 do
        Write(Q[v]: 4);
      writeln('>.');
    end;
  end;
................................
вызов из основной программы
  ShowPath(k, m, C, B);
Это образец. Он даже компилироваться не будет - т.к. в заголовке процедуры нельзя формировать тип переменных. Но если ты опишешь в самом начале тип TArray = array[1..n] of integer; и будешь использовать его при описании переменных, то должно заработать.
PS Ты, наверное портировал код с C на Pascal, т.к. вместо булевого массива используешь целочисленный. И обозначения массивов сильно отличаются от интернет-описаний алгоритма.

Добавлено через 54 минуты
Я почитал Wikipedia и e-maxx. На их основе собрал свою тестовую программу. Проверял на графе из статьи в Wikipedia. В ней присутствуют типы с одинаковыми описаниями, но это из соображения, что номера вершин это всегда целые числа, а расстояния сейчас целые, а гипотетически могут быть и real. Программу проверял на FreePascal.
Кликните здесь для просмотра всего текста
Pascal
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
{
V - множество вершин графа (vertex)
E - множество рёбер графа
w[i,j] - вес (длина) ребра ij
a - вершина, расстояния от которой ищутся
U - множество посещённых вершин (used)
d[u] - по окончании работы алгоритма равно
       длине кратчайшего пути из a до вершины u (distance)
p[u] - по окончании работы алгоритма содержит кратчайший путь из a в u
       (предшествующий u элемент, previous)
}
program Dijkstra;
 
const
  INFINITY  = MaxInt;
  UNDEFINED = -1;
 
const
  Nmax = 6;
type
  TMatrix = array[0..Nmax - 1, 0..Nmax - 1] of integer;
  TVertexList = array[0..Nmax - 1] of integer;
  TDistance = array[0..Nmax - 1] of integer;
  TUsed = array[0..Nmax - 1] of boolean;
 
  function MinOf(const a: TDistance; const m: TUsed): integer;
  var
    i: integer;
    Imin: integer;
    Min: integer;
  begin
    i := low(a);
    while i <= high(a) do
    begin
      if not m[i] then
      begin
        Imin := i;
        Min  := a[i];
        break;
      end;
      inc(i);
    end;
    for i := Imin + 1 to high(a) do
      if (Min > a[i]) and not m[i] then
      begin
        Imin := i;
        Min  := a[i];
      end;
    MinOf := Imin;
  end;
 
  procedure DijkstrasAlgorithm(const W: TMatrix; a: integer;
  var D: TDistance; var P: TVertexList);
  var
    v: integer;
    U: TUsed;
    i, j: integer;
  begin
    {initialization    
      d[a]:=0; p[a]:=0;
      d[v]:=INFINITY; p[v]:=UNDEFINED; для всех вершин отличных от a
    }
    for v := low(D) to high(D) do
    begin
      if v = a then
      begin
        D[v] := 0;
        P[v] := UNDEFINED;
      end
      else
      begin
        D[v] := INFINITY;
        P[v] := UNDEFINED;
      end;
      U[v] := False;
    end;
    {основной цикл}
    for i := low(D) to high(D) do {пока есть нерассмотренные вершины}
    begin
      v := MinOf(D, U); {берём непосещённую вершину с минимальным d[v]}
      U[v] := True;     {отмечаем её как посещённую}
      for j := low(D) to high(D) do
        if W[v, j] <> INFINITY then
          if D[j] > D[v] + W[v, j] then
          begin
            D[j] := D[v] + W[v, j];
            P[j] := v;
          end;
    end;
  end;
 
  procedure ShowPath(A, B: integer; const P: TVertexList; const D: TDistance);
  var
    Q: TVertexList;
    Len: integer;
    v: integer;
  begin
    Len := 0;
    if D[B] = INFINITY then
      writeln('There is not exist path from ', A, ' to ', B, '.')
    else
    begin
      v := B;
      repeat
        Q[Len] := v;
        Inc(Len);
        v := P[v];
      until v=UNDEFINED;
      write('A path from ', A, ' to ', B, ' is <');
      for v := Len - 1 downto 0 do
        Write(Q[v]: 4);
      writeln('>.');
    end;
  end;
 
var
  W: TMatrix =
  (
    (00, 07, 09, 00, 00, 14),
    (07, 00, 10, 15, 00, 00),
    (09, 10, 00, 11, 00, 02),
    (00, 15, 11, 00, 06, 00),
    (00, 00, 00, 06, 00, 09),
    (14, 00, 02, 00, 09, 00)
  );
var
  i, j: integer;
  P: TVertexList;
  D: TDistance;
  A, B: integer;
begin
  {для упрощения ввода вместо INFINITY в матрице весов W я использовал нули
   Поэтому нужно удалить нули из матрицы весов, заменив их на бесконечность}
  for i := 0 to Nmax - 1 do
    for j := 0 to Nmax - 1 do
      if (i <> j) and (W[i, j] = 0) then
        W[i, j] := INFINITY;
  {Ввод начальной и конечной точек маршрута}
  A := 0;
  B := 4;
  {Обработка графа по алгоритму Дейкстры}
  DijkstrasAlgorithm(W, A, D, P);
  {контрольный вывод значений результирующих массивов}
  write('Distance: ');
  for i := low(D) to high(D) do
    Write(D[i]: 4);
  writeln;
  write('Previous: ');
  for i := low(P) to high(P) do
    Write(P[i]: 4);
  writeln;
  {вывод вершин по кратчайшему пути из A в B}
  ShowPath(A, B, P, D);
end.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
24.02.2015, 22:31
Помогаю со студенческими работами здесь

Найти кратчайший путь между двумя заданными пунктами
Прошу объявить общий сбор всех хакеров, нужно решить задачу на C++. У меня ВСТАЛА небольшая проблема, так как я не професси, я не могу...

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

Кратчайший путь между двумя точками на поверхности
Дано уравнение поверхности z=f(x,y) и две точки на поверхности. Требуется изобразить на одном графике саму поверхность и кратчайший путь от...

Написать функцию, определяющую кратчайший путь между указанными двумя вершинами графа
Задан граф, у которого для каждой дуги задана ее длина: ((a b 12) (s d 3) …). Написать функцию, определяющую кратчайший путь между...

Найти минимальное количество пересадок между двумя городами
Здраствуйте!Помогите пожалуйста Кратчайший путь. Даны N городов и связи между ними в виде матрицы смежности. Требуется найти...


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

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит переходные токи и напряжения на элементах схемы. . . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru