#c# #algorithm #graph #a-star
#c# #алгоритм #График #a-star
Вопрос:
Я пытался следовать псевдокоду A * star вики, и у меня возникли проблемы с созданием метода эвристического значения, поэтому я просто использовал его как кратчайший доступ, но код продолжает добавлять начальный узел в closedSet .
public uint TotalNodes = 0;
uint[][] Neighbors = null;
uint[][] Weights = null;
public Graph(uint v)
{
TotalNodes = v 1;
Neighbors = new uint[TotalNodes][];
Weights = new uint[TotalNodes][];
for (int i = 1; i < TotalNodes; i )
{
for (int j = 1; j < TotalNodes; j )
{
Neighbors[i] = new uint[TotalNodes];
Weights[i] = new uint[TotalNodes];
}
}
}
public void AddNeighbor(uint parent, uint neighbor, uint distance)
{
Neighbors[parent][neighbor] = neighbor;
Weights[parent][neighbor] = distance;
}
public void RunAstarAlgorithm(uint start, uint goal)
{
uint[] closedSet = new uint[TotalNodes];
uint[] openSet = new uint[TotalNodes];
uint[] g_score = new uint[TotalNodes];
uint[] f_score = new uint[TotalNodes];
uint openSetNodes = 0, closedSetNodes = 0;
uint currentNode = 0;
uint tentativePathCost = 0;
openSet[0] = start;
for (uint i = 0; i < TotalNodes; i )
{
if (i == start) f_score[i] = 0;
else f_score[i] = uint.MaxValue;
}
f_score[start] = g_score[start] (uint)HeuristicCostEstimate(start,goal);
while (openSet.Length != 0)
{
for (uint i = 1; i < TotalNodes; i )
{
if (f_score[i] == f_score.Min()) currentNode = i;
}
if (currentNode == goal)
{
ReconstructPath(closedSet, currentNode);
return;
}
for (uint i = 0; i < TotalNodes; i ) if (openSet[i] == currentNode) openSet[i] = 0;
closedSet[closedSetNodes] = currentNode;
closedSetNodes ;
foreach (uint neighbor in Neighbors[currentNode])
{
for (uint i = 0; i < TotalNodes; i )
{
if (closedSet.Contains(neighbor)) continue;
}
tentativePathCost = g_score[currentNode] Weights[currentNode][neighbor];
if (!openSet.Contains(neighbor) || tentativePathCost < g_score[neighbor])
{
g_score[neighbor] = tentativePathCost;
f_score[neighbor] = g_score[neighbor] (uint)HeuristicCostEstimate(neighbor,goal);
if (!openSet.Contains(neighbor))
{
openSet[openSetNodes] = neighbor;
openSetNodes ;
}
}
}
}
}
Найдите эвристическое значение:
public int HeuristicCostEstimate(uint start, uint goal)
{
Queue<uint> queue = new Queue<uint>();
queue.Enqueue(start);
bool[] visitedNodes = new bool[TotalNodes];
int[] distances = new int[TotalNodes];
for (uint i = 0; i < TotalNodes; i ) distances[i] = -1;
distances[start] = 0;
while(queue.Count > 0)
{
uint node = queue.Dequeue();
if (node == goal) break;
foreach(uint neighbor in Neighbors[node])
{
if (neighbor == 0) continue;
if(distances[neighbor] == -1)
{
distances[neighbor] = distances[node] 1;
queue.Enqueue(neighbor);
}
}
}
return distances[goal];
}
Итак, у меня есть этот график:
7-узловой граф
и, например. я хочу перейти от 1 к 5, поэтому путь должен быть 1-2-3-6-5, верно?
Мой график представлен в виде неровных массивов (игнорируйте первое (0) место, я начинаю с 1 для целей распечатки)
Массив соседей (первая строка представляет узлы, столбцы представляют их соседей:
(0)(1)(2)(3)(4)(5)(6)(7)
(0) 0 0 0 0 0 0 0 0
(1) 0 0 1 0 0 0 0 1
(2) 0 2 0 2 2 0 0 0
(3) 0 0 3 0 3 0 3 0
(4) 0 0 4 4 0 4 0 0
(5) 0 0 0 0 5 0 5 0
(6) 0 0 0 6 0 6 0 6
(7) 0 7 0 0 0 0 7 0
И массив веса (расстояния) (столбцы представляют их соседей и каково расстояние до них):
(0)(1)(2)(3)(4)(5)(6)(7)
(0) 0 0 0 0 0 0 0 0
(1) 0 0 2 0 0 0 0 5
(2) 0 2 0 3 7 0 0 0
(3) 0 0 3 0 4 0 3 0
(4) 0 0 7 4 0 6 0 0
(5) 0 0 0 0 5 0 1 0
(6) 0 0 0 2 0 1 0 10
(7) 0 5 0 0 0 0 10 0
Итак, как я мог бы достичь кратчайшего пути с помощью алгоритма *?
Комментарии:
1. Если у вас нет никакой дополнительной информации (кроме весов ребер и связности), на которой можно основывать эвристику, тогда вам следует просто использовать алгоритм Дейкстры.
2. К сожалению, мне приходится писать более сложный алгоритм, чем у Дейкстры.