不幸的是,您正在尝试做的是不可能。
为什么?
因为有不止一组点会产生上面的距离矩阵。
为了证明这一点,假设您有一张点地图,其距离对应于该矩阵。
现在在 Y 轴上反映这张地图。相对距离不变 => 不同的点图,相同的矩阵!
现在在 X 轴上反映这张地图。相对距离不变 => 不同的点图,相同的矩阵!
现在将其旋转 90 度。同样,距离不变 => 再次使用相同的矩阵!
你看到这里的模式了吗?
事实上,有无限个可能的 X、Y 点集可以生成您在上面显示的距离矩阵。
简而言之,没有一对一的映射。这是多对一的。当您从一组点转到距离矩阵时,您会丢弃有价值的信息,之后您将无法将其取回。
如果你只是想得到点之间的最短路径(而不关心坐标系),那么Dijkstra算法就是你所需要的。
在您的情况下,您在每个点之间都有直接距离,但可能想看看间接路径是否会更短。在这种情况下,以下控制台应用程序(刚刚编写并且除了您的数据之外大部分未经测试)应该可以满足您的需求:
namespace DijkstraTest
{
class Node
{
public Node(int index)
{
distanceFromStart = -1;
this.index = index;
}
public int distanceFromStart;
public bool visited;
public Node parent;
public int index;
}
class Dijkstra
{
private int[,] distanceMatrix;
private int size;
public Dijkstra(int[,] distanceMatrix)
{
this.distanceMatrix = distanceMatrix;
size = distanceMatrix.GetLength(0);
if (distanceMatrix.Rank != 2 || (size != distanceMatrix.GetLength(1)))
throw new ArgumentException("Matrix must be 2-D and square!");
}
public List<Node> GetShortestPath(int startPos, int endPos)
{
var nodes = Enumerable.Range(0, size).Select(i => new Node(i)).ToList();
nodes[startPos].distanceFromStart = 0;
var endNode = nodes[endPos];
while (!endNode.visited)
{
var currentNode = nodes.Where(i => !i.visited && i.distanceFromStart != -1)
.OrderBy(i => i.distanceFromStart).First();
foreach (var neighbour in nodes
.Where(i => !i.visited && distanceMatrix[currentNode.index, i.index] != -1))
{
var thisDistance = currentNode.distanceFromStart +
distanceMatrix[currentNode.index, neighbour.index];
if (neighbour.distanceFromStart == -1 || neighbour.distanceFromStart > thisDistance)
{
neighbour.distanceFromStart = thisDistance;
neighbour.parent = currentNode;
}
}
currentNode.visited = true;
}
// build the results working back
var retVal = new List<Node> {endNode};
while (endNode.parent != null)
{
endNode = endNode.parent;
retVal.Add(endNode);
}
retVal.Reverse();
return retVal;
}
}
class Program
{
static int[,] DistanceMatrix = {{-1, 24, 15, 27, 19, 16, 11, 33, 28, 30},
{24, -1, 28, 32, 29, 17, 20, 20, 27, 30},
{15, 28, -1, 19, 22, 12, 22, 29, 29, 15},
{27, 32, 19, -1, 29, 23, 13, 31, 20, 28},
{19, 29, 22, 29, -1, 24, 25, 17, 22, 23},
{16, 17, 12, 23, 24, -1, 22, 23, 21, 12},
{11, 20, 22, 13, 25, 22, -1, 28, 23, 19},
{33, 20, 29, 31, 17, 23, 28, -1, 28, 22},
{28, 27, 29, 20, 22, 21, 23, 28, -1, 25},
{30, 30, 15, 28, 23, 12, 19, 22, 25, -1}};
static void Main(string[] args)
{
var dijkstra = new Dijkstra(DistanceMatrix);
for (int i = 0; i < 10; i++)
{
for (int j = i; j < 10; j++)
{
var path = dijkstra.GetShortestPath(i, j);
// print complex paths that are shorter than just going straight there...
if (path.Count > 2)
{
Console.Write("From {0} to {1}: ", i,j);
foreach (var item in path)
{
Console.Write(" {0} ", item.index);
}
Console.WriteLine(": Total distance: {0}, Direct distance: {1}",
path.Last().distanceFromStart, DistanceMatrix[i,j]);
}
}
}
}
}
这是相当粗略的准备,但它似乎产生了合理的输出。使用您的距离矩阵,您将获得以下输出(比直接更短的间接路径):
From 0 to 3: 0 6 3 : Total distance: 24, Direct distance: 27
From 0 to 9: 0 5 9 : Total distance: 28, Direct distance: 30
From 1 to 9: 1 5 9 : Total distance: 29, Direct distance: 30
它基于*文章here,直接翻译成C#。