fork download
  1. <?php
  2.  
  3. /* http://d...content-available-to-author-only...2.net/ */
  4.  
  5. define('SUBWAY', "едешь на метро");
  6. define('FOOT', "идешь пешком");
  7. define('BUS', "едешь на автобусе");
  8.  
  9. define('P_PET', 0);
  10. define('P_CHK', 1);
  11. define('P_GOR', 2);
  12. define('P_SPO', 3);
  13. define('P_VAS', 4);
  14. define('P_KRE', 5);
  15. define('P_LET', 6);
  16. define('P_DVO', 7);
  17. define('P_ISA', 8);
  18. define('P_NOV', 9);
  19. define('P_RAS', 10);
  20. define('P_GOS', 11);
  21. define('P_SEN', 12);
  22. define('P_VLA', 13);
  23. define('P_VIT', 14);
  24. define('P_TEH', 15);
  25.  
  26. define('UNKNOWN', -1);
  27.  
  28. /* Чтобы не писать много раз array('time' => ..., 'by' => ...), используем функцию.
  29.   «canGet» переводится как «можно попасть» */
  30. function canGet($time, $byWhat) {
  31. return array('time' => $time, 'by' => $byWhat);
  32. }
  33.  
  34. $pointNames = array(
  35. P_PET => 'ст. м. Петроградская',
  36. P_CHK => 'ст. м. Чкаловская',
  37. P_GOR => 'ст. м. Горьковская',
  38. P_SPO => 'ст. м. Спортивная',
  39. P_VAS => 'ст. м. Василеостровская',
  40. P_KRE => 'Петропавловская крепость',
  41. P_LET => 'Летний сад',
  42. P_DVO => 'Дворцовая площадь',
  43. P_ISA => 'Исакиевский собор',
  44. P_NOV => 'Новая Голландия',
  45. P_RAS => 'Дом Раскольникова',
  46. P_GOS => 'Гостиный Двор',
  47. P_SEN => 'Сенная Площадь',
  48. P_VLA => 'ст. м. Владимирская',
  49. P_VIT => 'Витебский вокзал',
  50. P_TEH => 'Технологический Институт'
  51. );
  52.  
  53. $paths = array(
  54. P_PET => array(
  55. P_CHK => canGet(10, BUS),
  56. P_GOR => canGet(3, SUBWAY)
  57. ),
  58.  
  59. P_CHK => array(
  60. P_PET => canGet(10, BUS),
  61. P_SPO => canGet(3, SUBWAY)
  62. ),
  63.  
  64. P_GOR => array(
  65. P_PET => canGet(3, BUS),
  66. P_KRE => canGet(5, FOOT),
  67. P_GOS => canGet(6, SUBWAY)
  68. ),
  69.  
  70. P_SPO => array(
  71. P_CHK => canGet(3, SUBWAY),
  72. P_VAS => canGet(10, BUS),
  73. P_SEN => canGet(7, SUBWAY)
  74. ),
  75.  
  76. P_VAS => array(
  77. P_SPO => canGet(10, BUS),
  78. P_GOS => canGet(7, SUBWAY),
  79. P_NOV => canGet(11, FOOT)
  80. ),
  81.  
  82. P_KRE => array(
  83. P_GOR => canGet(5, FOOT)
  84. ),
  85.  
  86. P_LET => array(
  87. P_DVO => canGet(6, FOOT),
  88. P_GOS => canGet(7, FOOT)
  89. ),
  90.  
  91. P_DVO => array(
  92. P_ISA => canGet(6, FOOT),
  93. P_GOS => canGet(6, FOOT),
  94. P_LET => canGet(6, FOOT)
  95. ),
  96.  
  97. P_ISA => array(
  98. P_DVO => canGet(6, FOOT),
  99. P_NOV => canGet(5, FOOT)
  100. ),
  101.  
  102. P_NOV => array(
  103. P_VAS => canGet(11, FOOT),
  104. P_ISA => canGet(5, FOOT),
  105. P_RAS => canGet(7, BUS)
  106. ),
  107.  
  108. P_RAS => array(
  109. P_NOV => canGet(7, BUS),
  110. P_SEN => canGet(3, FOOT)
  111. ),
  112.  
  113. P_GOS => array(
  114. P_VAS => canGet(7, SUBWAY),
  115. P_SEN => canGet(3, SUBWAY),
  116. P_DVO => canGet(6, FOOT),
  117. P_GOR => canGet(6, SUBWAY),
  118. P_LET => canGet(7, FOOT),
  119. P_VLA => canGet(7, FOOT)
  120. ),
  121.  
  122. P_SEN => array(
  123. P_RAS => canGet(3, FOOT),
  124. P_SPO => canGet(7, SUBWAY),
  125. P_GOS => canGet(3, SUBWAY),
  126. P_VLA => canGet(4, SUBWAY),
  127. P_VIT => canGet(2, SUBWAY),
  128. P_TEH => canGet(3, SUBWAY)
  129. ),
  130.  
  131. P_VLA => array(
  132. P_SEN => canGet(4, SUBWAY),
  133. P_GOS => canGet(7, FOOT),
  134. P_VIT => canGet(3, SUBWAY)
  135. ),
  136.  
  137. P_VIT => array(
  138. P_SEN => canGet(2, SUBWAY),
  139. P_TEH => canGet(2, SUBWAY),
  140. P_VLA => canGet(3, SUBWAY)
  141. ),
  142.  
  143. P_TEH => array(
  144. P_SEN => canGet(3, SUBWAY),
  145. P_VIT => canGet(2, SUBWAY)
  146. )
  147. );
  148.  
  149.  
  150. /*Функция построения кратчайшего пути.
  151. Возвращает NULL, если кратчайший путь не содержит промежуточных нодов.
  152. Иначе, возвращает массив промежуточных нодов.
  153. */
  154. function getPath($start, $end, $interimStep){
  155. if ($interimStep[$start][$end] == INF) {
  156. return NULL;
  157. }
  158. $shortestPath = array();
  159. $temp = $end;
  160. while ($temp != UNKNOWN) {
  161. $temp = $interimStep[$start][$temp];
  162. array_unshift($shortestPath, $temp);
  163. }
  164. unset($shortestPath[0]);
  165. return $shortestPath;
  166. }
  167.  
  168. /*
  169. Функция вывода пути.
  170. */
  171. function printPath($startPoint, $endPoint, $shortestPath, $paths, $pointNames){
  172. echo "Начальная точка: \"{$pointNames[$startPoint]}\"\n";
  173. $temp = $startPoint;
  174. if ($shortestPath != NULL) {
  175. $temp = $startPoint;
  176. foreach ($shortestPath as $node) {
  177. echo "Из нее {$paths[$temp][$node]['by']} до точки \"{$pointNames[$node]}\" {$paths[$temp][$node]['time']} мин.\n";
  178. $temp = $node;
  179. }
  180. }
  181. echo "Из нее {$paths[$temp][$endPoint]['by']} до точки \"{$pointNames[$endPoint]}\" {$paths[$temp][$endPoint]['time']} мин.\n";
  182. echo "В итоге ты попадешь в точку \"{$pointNames[$endPoint]}\" за {$paths[$startPoint][$endPoint]['time']} мин. Приятной поездки!\n\n";
  183. }
  184.  
  185. $numberOfNodes = count($pointNames);
  186.  
  187. /*Делаем квадратную матрицу путей размера $numberOfNodes, которая будет содержать время кратчайшего пути.
  188. Если путь не существует, то присваиваем ему значение бесконечности.
  189. */
  190. foreach ($paths as $i => $array) {
  191. for ($j = 0; $j < $numberOfNodes; $j++) {
  192. if (isset($paths[$i][$j]['time']) == NULL) {
  193. $paths[$i][$j]['time'] = INF;
  194. }
  195. }
  196. }
  197.  
  198. //Массив, который будет содержать предпоследний шаг кратчайшего пути.
  199. $interimStep = array();
  200. for ($i = 0; $i < $numberOfNodes; $i++) {
  201. $interimStep[$i] = array_fill(0, $numberOfNodes, UNKNOWN);
  202. }
  203.  
  204. //Алгоритм Флойда-Уоршелла.
  205. for ($k = 0; $k < $numberOfNodes; $k++) {
  206. for ($i = 0; $i < $numberOfNodes; $i++) {
  207. for ($j = 0; $j < $numberOfNodes; $j++) {
  208. if (($paths[$i][$k]['time'] + $paths[$k][$j]['time']) < $paths[$i][$j]['time']) {
  209. $paths[$i][$j]['time'] = $paths[$i][$k]['time'] + $paths[$k][$j]['time'];
  210. $interimStep[$i][$j] = $k;
  211. }
  212. }
  213. }
  214. }
  215.  
  216. //Тут вылетает предпоследняя нода (дом Раскольникова), но время всего пути выводится корректно.
  217. $startPoint = 0; // Петроградская
  218. $endPoint = 9; // Новая Голландия
  219. $shortestPath = getPath($startPoint, $endPoint, $interimStep);
  220. printPath($startPoint, $endPoint, $shortestPath, $paths, $pointNames);
  221.  
  222. //Сенная Площадь -> Новая Голландия
  223. //Тут все выводится корректно.
  224. $startPoint = 12;
  225. $endPoint = 9;
  226. $shortestPath = getPath($startPoint, $endPoint, $interimStep);
  227. printPath($startPoint, $endPoint, $shortestPath, $paths, $pointNames);
  228.  
  229. $startPoint = P_VIT;
  230. $endPoint = P_NOV;
  231. $shortestPath = getPath($startPoint, $endPoint, $interimStep);
  232. printPath($startPoint, $endPoint, $shortestPath, $paths, $pointNames);
  233.  
  234. $startPoint = P_TEH;
  235. $endPoint = P_NOV;
  236. $shortestPath = getPath($startPoint, $endPoint, $interimStep);
  237. printPath($startPoint, $endPoint, $shortestPath, $paths, $pointNames);
  238.  
Success #stdin #stdout #stderr 0.01s 20520KB
stdin
Standard input is empty
stdout
Начальная точка: "ст. м. Петроградская"
Из нее едешь на метро до точки "ст. м. Горьковская" 3 мин.
Из нее едешь на метро до точки "Гостиный Двор" 6 мин.
Из нее едешь на метро до точки "Сенная Площадь" 3 мин.
Из нее  до точки "Новая Голландия" 10 мин.
В итоге ты попадешь в точку "Новая Голландия" за 22 мин. Приятной поездки!

Начальная точка: "Сенная Площадь"
Из нее идешь пешком до точки "Дом Раскольникова" 3 мин.
Из нее едешь на автобусе до точки "Новая Голландия" 7 мин.
В итоге ты попадешь в точку "Новая Голландия" за 10 мин. Приятной поездки!

Начальная точка: "Витебский вокзал"
Из нее едешь на метро до точки "Сенная Площадь" 2 мин.
Из нее  до точки "Новая Голландия" 10 мин.
В итоге ты попадешь в точку "Новая Голландия" за 12 мин. Приятной поездки!

Начальная точка: "Технологический Институт"
Из нее едешь на метро до точки "Сенная Площадь" 3 мин.
Из нее  до точки "Новая Голландия" 10 мин.
В итоге ты попадешь в точку "Новая Голландия" за 13 мин. Приятной поездки!

stderr
PHP Notice:  Undefined index: by in /home/YtmJVF/prog.php on line 182
PHP Notice:  Undefined index: by in /home/YtmJVF/prog.php on line 182
PHP Notice:  Undefined index: by in /home/YtmJVF/prog.php on line 182