fork download
  1. <?php
  2.  
  3. define('SUBWAY', 'sub');
  4. define('FOOT', 'foot');
  5. define('BUS', 'bus');
  6.  
  7. $transportName = array(
  8. SUBWAY => 'едешь на метро',
  9. FOOT => 'идешь пешком',
  10. BUS => 'едешь на автобусе'
  11. );
  12.  
  13. $startPoint = 'pet'; // Петроградская
  14. $endPoint = 'nov'; // Новая Голландия
  15.  
  16. $pointNames = array(
  17. 'pet' => 'ст. м. Петроградская',
  18. 'chk' => 'ст. м. Чкаловская',
  19. 'gor' => 'ст. м. Горьковская',
  20. 'spo' => 'ст. м. Спортивная',
  21. 'vas' => 'ст. м. Василеостровская',
  22. 'kre' => 'Петропавловская крепость',
  23. 'let' => 'Летний сад',
  24. 'dvo' => 'Дворцовая площадь',
  25. 'isa' => 'Исакиевский собор',
  26. 'nov' => 'Новая Голландия',
  27. 'ras' => 'Дом Раскольникова',
  28. 'gos' => 'Гостиный Двор',
  29. 'sen' => 'Сенная Площадь',
  30. 'vla' => 'ст. м. Владимирская',
  31. 'vit' => 'Витебский вокзал',
  32. 'teh' => 'Технологический Институт'
  33. );
  34.  
  35. $paths = array(
  36. 'pet' => array(
  37. 'chk' => canGet(10, BUS),
  38. 'gor' => canGet(3, SUBWAY)
  39. ),
  40.  
  41. 'chk' => array(
  42. 'pet' => canGet(10, BUS),
  43. 'spo' => canGet(3, SUBWAY)
  44. ),
  45.  
  46. 'gor' => array(
  47. 'pet' => canGet(3, BUS),
  48. 'kre' => canGet(5, FOOT),
  49. 'gos' => canGet(6, SUBWAY)
  50. ),
  51.  
  52. 'spo' => array(
  53. 'chk' => canGet(3, SUBWAY),
  54. 'vas' => canGet(10, BUS),
  55. 'sen' => canGet(7, SUBWAY)
  56. ),
  57.  
  58. 'vas' => array(
  59. 'spo' => canGet(10, BUS),
  60. 'gos' => canGet(7, SUBWAY),
  61. 'nov' => canGet(11, FOOT)
  62. ),
  63.  
  64. 'kre' => array(
  65. 'gor' => canGet(5, FOOT)
  66. ),
  67.  
  68. 'let' => array(
  69. 'dvo' => canGet(6, FOOT),
  70. 'gos' => canGet(7, FOOT)
  71. ),
  72.  
  73. 'dvo' => array(
  74. 'isa' => canGet(6, FOOT),
  75. 'gos' => canGet(6, FOOT),
  76. 'let' => canGet(6, FOOT)
  77. ),
  78.  
  79. 'isa' => array(
  80. 'dvo' => canGet(6, FOOT),
  81. 'nov' => canGet(5, FOOT)
  82. ),
  83.  
  84. 'nov' => array(
  85. 'vas' => canGet(11, FOOT),
  86. 'isa' => canGet(5, FOOT),
  87. 'ras' => canGet(7, BUS)
  88. ),
  89.  
  90. 'ras' => array(
  91. 'nov' => canGet(7, BUS),
  92. 'sen' => canGet(3, FOOT)
  93. ),
  94.  
  95. 'gos' => array(
  96. 'vas' => canGet(7, SUBWAY),
  97. 'sen' => canGet(3, SUBWAY),
  98. 'dvo' => canGet(6, FOOT),
  99. 'gor' => canGet(6, SUBWAY),
  100. 'let' => canGet(7, FOOT),
  101. 'vla' => canGet(7, FOOT)
  102. ),
  103.  
  104. 'sen' => array(
  105. 'ras' => canGet(3, FOOT),
  106. 'spo' => canGet(7, SUBWAY),
  107. 'gos' => canGet(3, SUBWAY),
  108. 'vla' => canGet(4, SUBWAY),
  109. 'vit' => canGet(2, SUBWAY),
  110. 'teh' => canGet(3, SUBWAY)
  111. ),
  112.  
  113. 'vla' => array(
  114. 'sen' => canGet(4, SUBWAY),
  115. 'gos' => canGet(7, FOOT),
  116. 'vit' => canGet(3, SUBWAY)
  117. ),
  118.  
  119. 'vit' => array(
  120. 'sen' => canGet(2, SUBWAY),
  121. 'teh' => canGet(2, SUBWAY),
  122. 'vla' => canGet(3, SUBWAY)
  123. ),
  124.  
  125. 'teh' => array(
  126. 'sen' => canGet(3, SUBWAY),
  127. 'vit' => canGet(2, SUBWAY)
  128. )
  129. );
  130.  
  131. function canGet($time, $byWhat)
  132. {
  133. return array('time' => $time, 'by' => $byWhat);
  134. }
  135.  
  136. /**
  137.   * Функция для инициализации начальных данных
  138.   *
  139.   * Функция принимает на вход начальную вершину, создает массивы для меток вершин
  140.   * и фиксирования посещения вершины, и возвращает их
  141.   *
  142.   * @global array $paths Глобальный массив вершин
  143.   * @param string $startPoint Начальная вершина
  144.   * @return array Чистый массив меток и посещений
  145.   */
  146. function initAlgorithm($startPoint)
  147. {
  148. global $paths;
  149.  
  150. /** Массив фиксирующий посещение метки */
  151. $visited = array();
  152.  
  153. /** Массив меток для вершин. Метка начальной вершины - 0, остальный - inf */
  154. $labels = array();
  155.  
  156. foreach ($paths as $point => $pointValue) {
  157. $labels[$point] = PHP_INT_MAX;
  158. $visited[$point] = false;
  159. }
  160. $labels[$startPoint] = 0;
  161.  
  162. $result = array();
  163. $result['labels'] = $labels;
  164. $result['visited'] = $visited;
  165.  
  166. return $result;
  167. }
  168.  
  169. /**
  170.   * Функция выполняющая алгоритм Дейскры
  171.   *
  172.   * @global $paths Глобальный массив вершин
  173.   * @param array $labels Массив меток вершин
  174.   * @param array $visited Массив посещения вершин
  175.   * @return array
  176.   */
  177. function doAlgorithmDijstra($labels, $visited)
  178. {
  179. global $paths;
  180.  
  181. /** Количество вершин */
  182. $countPoint = count($paths);
  183.  
  184. for ($i = 0; $i < $countPoint; $i++) {
  185.  
  186. /** Поиск вершины с наименьшей меткой */
  187. $minLabel = PHP_INT_MAX;
  188.  
  189. /** Вершина с которой работаем в данный момент */
  190. $workPoint = NULL;
  191.  
  192. foreach ($labels as $label => $value) {
  193. if (($value < $minLabel) && (!$visited[$label])) {
  194. $minLabel = $value;
  195. $workPoint = $label;
  196. }
  197. }
  198.  
  199. /** Получение всех вершин, которые соединяются с текущей */
  200. $nextPoint = $paths[$workPoint];
  201.  
  202. /** Перерасчет меток соседних вершин */
  203. foreach ($nextPoint as $point => $valuePoint) {
  204. $newLabel = $labels[$workPoint] + $nextPoint[$point]['time'];
  205. if ($labels[$point] > $newLabel) {
  206. $labels[$point] = $newLabel;
  207. }
  208. }
  209.  
  210. /** Помечаем вершину, как посещенную */
  211. $visited[$workPoint] = true;
  212. }
  213.  
  214. return $labels;
  215. }
  216.  
  217. /**
  218.   * Функция восстановления пути по массиву меток
  219.   *
  220.   * @global $paths Глобальный массив вершин
  221.   * @param string $startPoint Начальная вершина
  222.   * @param string $endPoint Конечная вершина
  223.   * @param array $labels Массив меток вершин
  224.   * @return array Искомый путь
  225.   */
  226. function restorationPath($startPoint, $endPoint, $labels)
  227. {
  228. global $paths;
  229.  
  230. /** Текущая вершина */
  231. $currentPoint = $endPoint;
  232. $targetPath = array($currentPoint);
  233.  
  234. while ($currentPoint != $startPoint) {
  235. foreach ($paths[$currentPoint] as $nextPoint => $nextPointValue) {
  236. if ($labels[$currentPoint] - $paths[$currentPoint][$nextPoint]['time'] == $labels[$nextPoint]) {
  237. $targetPath[] = $nextPoint;
  238. $currentPoint = $nextPoint;
  239. break;
  240. }
  241. }
  242. }
  243.  
  244. $targetPath = array_reverse($targetPath);
  245. return $targetPath;
  246. }
  247.  
  248.  
  249. /**
  250.   * Функция печати оптимального пути
  251.   *
  252.   * Функция принимает начальную и конечную вершину пути,
  253.   * массив меток, массив оптимального пути, и выводит последний
  254.   *
  255.   * @global $paths Глобальный массив вершин
  256.   * @global $pointNames Глобальный массив "человеческих" названий вершин
  257.   * @global $transportName Глобальны массив передвижения из точки А в точку Б
  258.   * @param string $startPoint Начальная вершина
  259.   * @param string $endPoint Конечная вершина
  260.   * @param array $targetPath Массив оптимального пути
  261.   * @param array $finalLabel Массив итоговых меток
  262.   * @return void
  263.   */
  264. function printTargetPath($startPoint, $endPoint, $targetPath, $finalLabel)
  265. {
  266. global $paths;
  267. global $pointNames;
  268. global $transportName;
  269.  
  270. $countTargetPoint = count($targetPath);
  271.  
  272. echo "Начальная точка: {$pointNames[$startPoint]}\n";
  273. for ($i = 0; $i < $countTargetPoint - 1; $i++) {
  274. /** Определение випа транспорта */
  275. $nmtransport = $transportName[$paths[$targetPath[$i]][$targetPath[$i + 1]]['by']];
  276. echo "Из нее {$nmtransport} до точки {$pointNames[$targetPath[$i + 1]]} {$paths[$targetPath[$i]][$targetPath[$i + 1]]['time']} минут\n";
  277. }
  278. echo "В итоге ты попадаешь в точку " . $pointNames[$endPoint] . " за " . $finalLabel[$endPoint] . " минут. Приятной поездки!" ;
  279. }
  280.  
  281. /** Массив меток и посещений*/
  282. $cleanLabel = array();
  283. $cleanLabel = initAlgorithm($startPoint);
  284.  
  285. /** Результат работы алгоритма */
  286. $finalLabel = array();
  287. $finalLabel = doAlgorithmDijstra($cleanLabel['labels'], $cleanLabel['visited']);
  288.  
  289. /** Оптимальный путь */
  290. $targetPath = array();
  291. $targetPath = restorationPath($startPoint, $endPoint, $finalLabel);
  292. printTargetPath($startPoint, $endPoint, $targetPath, $finalLabel);
  293. ?>
Success #stdin #stdout 0.01s 52488KB
stdin
Standard input is empty
stdout
Начальная точка: ст. м. Петроградская
Из нее едешь на метро до точки ст. м. Горьковская 3 минут
Из нее едешь на метро до точки Гостиный Двор 6 минут
Из нее едешь на метро до точки Сенная Площадь 3 минут
Из нее идешь пешком до точки Дом Раскольникова 3 минут
Из нее едешь на автобусе до точки Новая Голландия 7 минут
В итоге ты попадаешь в точку Новая Голландия за 22 минут. Приятной поездки!