将点之间的距离转换为点

时间:2014-04-03 04:42:11

标签: c# matrix distance coordinate

给定起点和距离,计算目的地点。 我有一个与客户的矩阵,它与彼此之间的距离。 (见链接jsfiddle)

矩阵:http://jsfiddle.net/j69kA/

如何根据中心点将其转换为坐标点(X,Y)?哪个可以是1.

    1   2   3   4   5   6   7   8   9   10
1   0   24  15  27  19  16  11  33  28  30
2   24  0   28  32  29  17  20  20  27  30
3   15  28  0   19  22  12  22  29  29  15
4   27  32  19  0   29  23  13  31  20  28
5   19  29  22  29  0   24  25  17  22  23
6   16  17  12  23  24  0   22  23  21  12
7   11  20  22  13  25  22  0   28  23  19
8   33  20  29  31  17  23  28  0   28  22
9   28  27  29  20  22  21  23  28  0   25
10  30  30  15  28  23  12  19  22  25  0

2 个答案:

答案 0 :(得分:1)

遗憾的是,不可能

为什么?

因为有多组点可以产生上面的距离矩阵。

为了证明这一点,想象一下你有一个点的地图,其距离对应于那个矩阵。

现在在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#。

答案 1 :(得分:0)

要构建笛卡尔系统,您需要两个点 - &gt;来源,目的地

您的矩阵仅包含两点之间的距离,而不包含原点和目的地。

您需要将其转换为笛卡尔坐标系(使用XY平面)。

你说原点是1。

你如何建议这个系统,因为它不能是笛卡儿,因为在这种情况下你想要目的地点。

我建议使用极坐标系,两点之间的角度相等。

修改 来自http://www.c-program-example.com/

使用:

#include "stdio.h"
#define infinity 999

void dij(int n,int v,int cost[10][10],int dist[])
{
  int i,u,count,w,flag[10],min;
  for(i=1;i<=n;i++)
        flag[i]=0,dist[i]=cost[v][i];
  count=2;
  while(count<=n)
  {
        min=99;
        for(w=1;w<=n;w++)
              if(dist[w]<min && !flag[w])
                    min=dist[w],u=w;
        flag[u]=1;
        count++;
        for(w=1;w<=n;w++)
              if((dist[u]+cost[u][w]<dist[w]) && !flag[w])
                    dist[w]=dist[u]+cost[u][w];
  }
}

void start()
{
  int n,v,i,j,cost[10][10],dist[10];
  printf("\n Enter the number of nodes:");
  scanf("%d",&n);
  printf("\n Enter the cost matrix:\n");
  for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
        {
              scanf("%d",&cost[i][j]);
                    if(cost[i][j]==0)
              cost[i][j]=infinity;
        }
  printf("\n Enter the source matrix:");
  scanf("%d",&v);
  dij(n,v,cost,dist);
  printf("\n Shortest path:\n");
  for(i=1;i<=n;i++)
        if(i!=v)
              printf("%d->%d,cost=%d\n",v,i,dist[i]);
}