fork(1) download
  1. <?php
  2.  
  3.  
  4. define('SUBWAY', 'sub');
  5. define('FOOT', 'foot');
  6. define('BUS', 'bus');
  7.  
  8. $transportName = array(
  9. SUBWAY => 'едешь на метро',
  10. FOOT => 'идешь пешком',
  11. BUS => 'едешь на автобусе'
  12. );
  13.  
  14. $startPoint = 'pet'; // Петроградская
  15. $endPoint = 'nov'; // Новая Голландия
  16.  
  17. $pointNames = array(
  18. 'pet' => 'ст. м. Петроградская',
  19. 'chk' => 'ст. м. Чкаловская',
  20. 'gor' => 'ст. м. Горьковская',
  21. 'spo' => 'ст. м. Спортивная',
  22. 'vas' => 'ст. м. Василеостровская',
  23. 'kre' => 'Петропавловская крепость',
  24. 'let' => 'Летний сад',
  25. 'dvo' => 'Дворцовая площадь',
  26. 'isa' => 'Исакиевский собор',
  27. 'nov' => 'Новая Голландия',
  28. 'ras' => 'Дом Раскольникова',
  29. 'gos' => 'Гостиный Двор',
  30. 'sen' => 'Сенная Площадь',
  31. 'vla' => 'ст. м. Владимирская',
  32. 'vit' => 'Витебский вокзал',
  33. 'teh' => 'Технолоческий Институт'
  34. );
  35.  
  36. $paths = array(
  37. 'pet' => array(
  38. 'chk' => canGet(10, BUS),
  39. 'gor' => canGet(3, SUBWAY)
  40. ),
  41.  
  42. 'chk' => array(
  43. 'pet' => canGet(10, BUS),
  44. 'spo' => canGet(3, SUBWAY)
  45. ),
  46.  
  47. 'gor' => array(
  48. 'pet' => canGet(3, BUS),
  49. 'kre' => canGet(5, FOOT),
  50. 'gos' => canGet(6, SUBWAY)
  51. ),
  52.  
  53. 'spo' => array(
  54. 'chk' => canGet(3, SUBWAY),
  55. 'vas' => canGet(10, BUS),
  56. 'sen' => canGet(7, SUBWAY)
  57. ),
  58.  
  59. 'vas' => array(
  60. 'spo' => canGet(10, BUS),
  61. 'gos' => canGet(7, SUBWAY),
  62. 'nov' => canGet(11, FOOT)
  63. ),
  64.  
  65. 'kre' => array(
  66. 'gor' => canGet(5, FOOT)
  67. ),
  68.  
  69. 'let' => array(
  70. 'dvo' => canGet(6, FOOT),
  71. 'gos' => canGet(7, FOOT)
  72. ),
  73.  
  74. 'dvo' => array(
  75. 'isa' => canGet(6, FOOT),
  76. 'gos' => canGet(6, FOOT),
  77. 'let' => canGet(6, FOOT)
  78. ),
  79.  
  80. 'isa' => array(
  81. 'dvo' => canGet(6, FOOT),
  82. 'nov' => canGet(5, FOOT)
  83. ),
  84.  
  85. 'nov' => array(
  86. 'vas' => canGet(11, FOOT),
  87. 'isa' => canGet(5, FOOT),
  88. 'ras' => canGet(7, BUS)
  89. ),
  90.  
  91. 'ras' => array(
  92. 'nov' => canGet(7, BUS),
  93. 'sen' => canGet(3, FOOT)
  94. ),
  95.  
  96. 'gos' => array(
  97. 'vas' => canGet(7, SUBWAY),
  98. 'sen' => canGet(3, SUBWAY),
  99. 'dvo' => canGet(6, FOOT),
  100. 'gor' => canGet(6, SUBWAY),
  101. 'let' => canGet(7, FOOT),
  102. 'vla' => canGet(7, FOOT)
  103. ),
  104.  
  105. 'sen' => array(
  106. 'ras' => canGet(3, FOOT),
  107. 'spo' => canGet(7, SUBWAY),
  108. 'gos' => canGet(3, SUBWAY),
  109. 'vla' => canGet(4, SUBWAY),
  110. 'vit' => canGet(2, SUBWAY),
  111. 'teh' => canGet(3, SUBWAY)
  112. ),
  113.  
  114. 'vla' => array(
  115. 'sen' => canGet(4, SUBWAY),
  116. 'gos' => canGet(7, FOOT),
  117. 'vit' => canGet(3, SUBWAY)
  118. ),
  119.  
  120. 'vit' => array(
  121. 'sen' => canGet(2, SUBWAY),
  122. 'teh' => canGet(2, SUBWAY),
  123. 'vla' => canGet(3, SUBWAY)
  124. ),
  125.  
  126. 'teh' => array(
  127. 'sen' => canGet(3, SUBWAY),
  128. 'vit' => canGet(2, SUBWAY)
  129. )
  130. );
  131.  
  132. /* Чтобы не писать много раз array('time' => ..., 'by' => ...), используем функцию.
  133.   «canGet» переводится как «можно попасть» */
  134. function canGet($time, $byWhat)
  135. {
  136. return array('time' => $time, 'by' => $byWhat);
  137. }
  138.  
  139. # Возвращает ближайший узел
  140. function lowestWeightNode($weightOfActiveNodes)
  141. {
  142. $lowestWeight = INF;
  143. $lowestNode = null;
  144. foreach ($weightOfActiveNodes as $node => $weightNode) {
  145. if ($lowestWeight > $weightNode) {
  146. $lowestWeight = $weightNode;
  147. $lowestNode = $node;
  148. }
  149. }
  150. return $lowestNode;
  151. }
  152.  
  153. function searchForAWay($startPoint, $endPoint, $paths, $transportName, $pointNames)
  154. {
  155. $point = array_keys($paths);
  156. $weightOfActiveNodes = array_fill_keys($point, INF); // Массив с весами узлов
  157. $parentsNode = array_fill_keys($point, '');; // Массив с родительскикими узлами
  158. $weightOfProcessedKnots = []; // Массив для обработаннхы узлов
  159.  
  160. $weightOfActiveNodes[$startPoint] = 0; // Стартовой точке присваивается 0, для того, алгоритм поиска пути начался с неё
  161. $node = lowestWeightNode($weightOfActiveNodes); // Находит узел с наименьшим весом
  162.  
  163. while ($node != $endPoint) {
  164. foreach ($paths[$node] as $neighbor => $timeAndBy) {
  165. if (array_key_exists($neighbor, $weightOfActiveNodes)) { //
  166. $weightNeighbor = $weightOfActiveNodes[$node] + $timeAndBy['time']; // весСоседа = рассматриваемый узел + путь до соседа
  167. if ($weightOfActiveNodes[$neighbor] > $weightNeighbor) { // Если текущий вес узла (рассматриваемого соседа) больше чем , новый найденный
  168. $parentsNode[$neighbor] = $node;
  169. $weightOfActiveNodes[$neighbor] = $weightNeighbor;
  170. }
  171. }
  172. }
  173. $weightOfProcessedKnots[$node] = $weightOfActiveNodes[$node];
  174. unset($weightOfActiveNodes[$node]);
  175. $node = lowestWeightNode($weightOfActiveNodes);
  176. }
  177.  
  178. $commonPath = []; // Кратчайший, требуемый путь
  179. $finishPoint = $endPoint;
  180. while ($finishPoint != $startPoint) {
  181. $commonPath[$finishPoint] = $parentsNode[$finishPoint];
  182. $finishPoint = $parentsNode[$finishPoint];
  183. }
  184. $commonPath = array_reverse($commonPath);
  185.  
  186. #Вывод пути
  187. $totalTime = 0;
  188. foreach ($commonPath as $startPoint => $FinishPoint) {
  189. $wayOfMovement = $transportName[$paths[$startPoint][$FinishPoint]['by']];
  190. echo "Из неё {$wayOfMovement} до точки {$pointNames[$startPoint]} {$paths[$startPoint][$FinishPoint]['time']} мин." . PHP_EOL;
  191. $totalTime += $paths[$startPoint][$FinishPoint]['time'];
  192. }
  193. echo "В итоге ты попадешь в точку {$pointNames[$endPoint]} за {$totalTime} минут";
  194. }
  195.  
  196. searchForAWay($startPoint, $endPoint, $paths, $transportName, $pointNames);
Success #stdin #stdout 0.02s 24592KB
stdin
Standard input is empty
stdout
Из неё едешь на автобусе до точки ст. м. Горьковская 3 мин.
Из неё едешь на метро до точки Гостиный Двор 6 мин.
Из неё едешь на метро до точки Сенная Площадь 3 мин.
Из неё идешь пешком до точки Дом Раскольникова 3 мин.
Из неё едешь на автобусе до точки Новая Голландия 7 мин.
В итоге ты попадешь в точку Новая Голландия за 22 минут