Я пытаюсь найти наилучший путь в графе, используя алгоритм Беллмана-Форда. Однако вместо того, чтобы использовать сумму всех ребер для вычисления длины пути, мне нужен путь с наименьшими потерями. Мы рассчитываем потери по следующей формуле: remainingSoldiers = sqrt(a^2 - b^2)
, где A — наша армия, B — вражеская армия, а restSoldiers — количество наших солдат, оставшихся после боя.
Пример: Допустим, мы хотим захватить город D. Мы начинаем в вершине A с армией силой 100. Наша армия движется в вершину B, которую патрулирует вражеская армия численностью 50. Согласно нашей формуле, у нас есть 86 солдаты ушли. Далее наша армия движется в вершину C, поэтому наши 86 солдат сражаются с 40 солдатами, патрулирующими вершину C, и у нас осталось 76 солдат. И, наконец, наши 76 солдат отправляются в вершину D, которую охраняют 70 вражеских солдат. Согласно нашей формуле мы покорили вершину D с 29 солдатами.
Итак, чтобы найти лучший путь, мы должны рассчитать, какой путь выбрать, чтобы иметь наименьшие потери. Подсказка, которую я получил, состоит в том, чтобы установить силу нашей армии и силу вражеской армии как веса ребер и использовать Беллмана-Форда с модифицированным алгоритмом релаксации, чтобы найти лучший путь поиска. Это именно то, что я сделал в своем коде ниже.
Я понял, что для того, чтобы найти лучший путь, я должен найти путь с наименьшим числом потерь, а не с наибольшим количеством оставшихся солдат, поскольку поиск пути с наибольшим числом — это NP-полная задача.
Мой код следующий (я использую пользовательскую библиотеку для графиков, но она должна быть очень простой и понятной):
public Map<Vertex, Double> bellmanFord(Vertex s) {
Map<Vertex, Double> d = g.createVertexMap(Double.POSITIVE_INFINITY);
d.put(s, 0d);
for (int i = 0; i < g.getVertices().size(); i++)
for (Edge e : g.getEdges())
relax(e, d);
return d;
}
public void relax(Edge e, Map<Vertex, Double> d) {
Vertex u = e.getSource();
Vertex v = e.getTarget();
if (d.get(u) + e.getWeight() < d.get(v))
d.put(v, d.get(u) + e.getWeight());
}
И ниже мой модифицированный код для релаксации:
public void relax(Edge e, Map<Vertex, Double> d) {
Vertex u = e.getSource();
Vertex v = e.getTarget();
if (d.get(u) - formula(g.getEdge(u, v).getWeight(), g.getEdge(v, u).getWeight()) > d.get(v))
d.put(v, d.get(u) - formula(g.getEdge(u, v).getWeight(), g.getEdge(v, u).getWeight()));
}
public double formula(double ourCity, double enemyCity) {
double a = Math.pow(ourCity, 2);
double b = Math.pow(enemyCity, 2);
double result = a - b;
return Math.sqrt(result);
}
Однако мой код выводит полную ерунду. Не могли бы вы помочь мне решить мою проблему и реализовать формулу внутри релаксации метода для алгоритма Беллмана-Форда?
Это график, с которым я запускаю свой код (не крайний случай, просто случайный график для проверки базовой функциональности): https://i.imgur.com/Y2OhfDj.png . Мы пытаемся захватить город H из города A. Наша армия численностью 120 человек находится в городе A. При запуске моего модифицированного кода bellman-ford выводит следующее: {a=Infinity, d=Infinity, f=Infinity, g=Infinity, b=Infinity, c=Infinity, h=Infinity, e=Infinity}.
Я думаю, что мне нужно каким-то образом изменить ребра, представляющие силу моей армии, в соответствии с моим алгоритмом (я могу использовать метод .setWeight() на любом ребре..), но непонятно, как это реализовать. Я испробовал множество вариантов релаксации, но пока ни один из них не приблизился к правильному ответу.
Спасибо!
A
будет начальным количеством солдат. Осталось солдат в квадрате после первого столкновения:R1^2 = A^2 - B1^2
. После второй встречи:R2^2 = R1^2 - B2^2 = A^2 - B1^2 - B2^2
. После k встреч:Rk^2 = A^2 - B1^2 - ... - Bk^2
. Итак, это, по сути, проблема с кратчайшей частью... Но вы должны возвести в квадрат свои веса ребер. - person   schedule 16.08.2019