mihaild, спасибо. Вы не представляете, как конкретные ссылки помогают, когда интернет тормозит и странички грузятся по пять-десять минут (если вообще грузятся)!
Вариант с использованием фибоначчиевой кучи мне пока переварить не под силу. В Java нет для неё готовой реализации, а самому такие вещи писать или разбираться в чужом коде — та ещё морока. Так что откладывается для будущего изучения. Там ещё вопросы с производительностью: куча имеет большой временной множитель и на малых графах проигрывает.
Разобрался вроде бы с алгоритмом и-макс. Реализовал вариант с упорядоченным множеством. Не уверен, что повторил дословно, потому что про стандартную библиотеку плюсов знаю только по наслышке. Но код, вроде, работает:
import java.util.*;
public class Study_Modified_BFS_Dijkstra {
private static final int spaceStepTime = 1;
private static final int dotStepTime = 3;
private static final String [] sourceMap = {
" ..... ",
" . . ........ ",
" .. ... ...... . ",
" . . ... .. ",
" .. ",
" ... ",
" .... .. . ",
" . . . . .. ",
" .. .... . .. ",
" ....... . ",
" ..... .. ",
". ....... . ",
"........ . . ",
" .. .. ",
" . ........ ",
" .. .......",
" .. ...... ...",
" .......... ",
" ... ... ",
" .... "
};
private static int width, height;
private static int [] [] stepTimeMap;
private static int [] [] travelTimeMap;
private static int iterationsCount;
private static int comparisonsCount;
public static void main (String [] args) {
initializeMaps ();
iterationsCount = 0;
comparisonsCount = 0;
performDijkstraSearch (new Position (0, 0));
displayTravelMap ();
System .out .println ("Iterations Count = " + iterationsCount);
System .out .println ("Comparisons Count = " + comparisonsCount);
}
private static void initializeMaps () {
int k, l;
height = sourceMap .length;
width = sourceMap [0] .length ();
stepTimeMap = new int [height] [width];
travelTimeMap = new int [height] [width];
for (k = 0; height > k; ++k) {
for (l = 0; width > l; ++l) {
switch (sourceMap [k] .charAt (l)) {
case '.':
stepTimeMap [k] [l] = dotStepTime;
break;
default:
stepTimeMap [k] [l] = spaceStepTime;
}
travelTimeMap [k] [l] = Integer .MAX_VALUE;
}
}
}
private static void performDijkstraSearch (Position startPosition) {
int k, time;
SortedSet <Position> positionsSet;
Position [] neighbors;
Position currentPosition, newPosition;
positionsSet = new TreeSet <> ();
startPosition .setTravelTime (0);
positionsSet .add (startPosition);
while (!positionsSet .isEmpty ()) {
currentPosition = positionsSet .first ();
positionsSet .remove (currentPosition);
neighbors = currentPosition .getNeighbors ();
for (k = 0; neighbors .length > k; ++k) {
newPosition = neighbors [k];
time = currentPosition .getTravelTime () + newPosition .getStepTime ();
if (newPosition .getTravelTime () > time) {
positionsSet .remove (newPosition);
newPosition .setTravelTime (time);
positionsSet .add (newPosition);
}
}
++iterationsCount;
}
}
private static void displayTravelMap () {
int k, l;
for (k = 0; height > k; ++k) {
for (l = 0; width > l; ++l) {
System .out .print (String .format ("%3d", travelTimeMap [k] [l]));
}
System .out .println ();
}
System .out .println ();
}
private static class Position implements Comparable <Position> {
private int x, y;
public Position (int arg_x, int arg_y) {
x = arg_x;
y = arg_y;
}
public int getStepTime () {
return stepTimeMap [y] [x];
}
public int getTravelTime () {
return travelTimeMap [y] [x];
}
public void setTravelTime (int value) {
travelTimeMap [y] [x] = value;
}
public Position [] getNeighbors () {
int count;
Position [] result;
count = 4;
if (0 == x || width == x + 1) {
--count;
}
if (0 == y || height == y + 1) {
--count;
}
result = new Position [count];
count = 0;
if (0 < y) {
result [count] = new Position (x, y - 1);
++count;
}
if (0 < x) {
result [count] = new Position (x - 1, y);
++count;
}
if (width > x + 1) {
result [count] = new Position (x + 1, y);
++count;
}
if (height > y + 1) {
result [count] = new Position (x, y + 1);
}
return result;
}
@Override
public int compareTo (Position arg) {
int value;
++comparisonsCount;
value = travelTimeMap [y] [x] - travelTimeMap [arg .y] [arg .x];
if (0 != value) {
return value;
}
value = y - arg .y;
if (0 != value) {
return value;
}
return x - arg .x;
}
}
}
Результат работы:
0 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 28 31 34 37 38 37
1 2 3 4 5 6 9 8 9 12 11 12 13 14 15 16 17 18 19 20 23 24 25 26 27 28 31 34 33 34 35 36
2 3 4 5 8 9 10 11 12 15 12 13 14 15 16 17 18 19 22 23 26 27 28 29 28 29 30 31 32 35 36 37
3 4 5 8 9 12 11 12 13 14 13 14 15 16 17 18 19 20 21 24 27 28 27 28 29 30 31 32 35 38 37 38
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 33 36 37 38 39
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 33 36 39 38 39 40
6 7 8 11 12 13 14 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 33 36 37 40 39 40 41
7 8 11 12 13 16 15 16 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 33 34 37 40 41 40 41 42
8 9 12 15 14 15 18 19 18 19 18 21 20 21 22 23 24 25 26 27 28 29 30 31 34 37 38 39 40 41 42 43
9 10 11 12 13 14 15 16 19 22 21 24 23 24 25 24 25 26 27 28 29 30 31 32 33 36 37 38 39 40 41 42
10 13 14 15 16 17 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 34 35 34 35 36 37 38 39 40 41
13 14 17 18 19 20 19 20 21 20 21 22 23 24 25 26 27 28 29 30 31 32 33 36 35 36 37 38 39 40 41 42
16 17 20 21 22 23 22 23 22 21 22 25 24 25 26 27 28 29 30 31 32 33 34 35 38 37 38 39 40 41 42 43
17 18 19 22 25 24 23 24 23 22 23 24 27 28 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
18 19 20 21 22 23 24 25 24 23 24 25 26 29 28 29 30 31 32 33 36 37 38 39 40 41 42 43 42 43 44 45
19 20 21 22 23 24 25 26 25 24 25 26 27 30 31 30 31 32 33 34 35 36 37 38 39 42 45 46 45 46 47 48
20 21 22 23 24 25 26 27 26 25 26 27 28 29 32 33 32 33 36 37 38 39 40 41 40 41 42 43 44 47 50 51
21 22 23 24 25 26 27 28 27 26 27 28 29 30 31 32 33 36 39 40 41 42 43 44 43 44 45 44 45 46 47 48
22 23 24 25 26 27 28 29 28 27 28 29 30 31 32 33 34 35 36 39 42 43 42 43 44 45 46 47 48 49 48 49
23 24 25 26 27 28 29 30 29 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 46 49 50 51 50 49 50
Iterations Count = 640
Comparisons Count = 9099
Сишники ещё любят свой код оформлять, так что сам чёрт ногу сломит об обилие знаков препинания и однобуквенных переменных. Нет бы писать осмысленные названия для переменных и методов. Чтобы код можно было читать как прозу. Тем не менее, надо будет попробовать реализовать тот же код, но с приоритетной очередью и кастомарным компаратором, и сравнить быстродействие.
Ещё у меня тут возникла такая мысль. Вернее встала необходимость. Пусть имеется карта, правда уже с унивариантым шагом от ячейки к ячейке и, возможно, непроходимыми ячейками. Но на ней есть сразу много стартовых позиций. Если после расчёта расстояний эти позиции по одной удалять, то можно ли реализовать алгоритм пересчёта карты расстояний, чтобы не рассчитывать её заново целиком?