【问题标题】:What is the most efficient way to represent edge weights for Dijkstra's algorithm代表 Dijkstra 算法的边权重的最有效方法是什么
【发布时间】:2015-06-20 20:59:12
【问题描述】:

我正在制作一个小游戏,我将让一个角色在网格上四处移动。当他们四处走动时,我打算使用 Dijkstra 的算法进行寻路。唯一的问题是我想像这样制作薄壁(而不仅仅是删除节点):http://i.gyazo.com/85d110c17cf027d3ad0219fa26938305.png

我认为最好的方法就是将 2 个方格之间的边权重编辑得如此之高,以至于它永远不会被越过。无论如何,关于这个问题:

为网格中的每个连接分配边权重的最有效方法是什么?

我考虑过使用邻接矩阵,但对于 15x6 的网格,这是一个 90x90 的矩阵,这似乎...过多。任何帮助都会很好,谢谢(:

【问题讨论】:

  • (1) 您的图表似乎没有加权,因此您可以使用 BFS,在这种情况下,它比 Dijkstra 的算法更简单、更有效。 (2) 90x90 矩阵对于现代机器来说几乎不是问题。 (3) 如果你使用double 作为权重,很多语言都有你可以使用的无穷大值。在java中Double.POSITIVE_INFINITY (4) 你总是可以使用邻接列表

标签: algorithm grid dijkstra path-finding


【解决方案1】:

您只需要存储直线正方形之间的边,一个正方形最多可以有 4 个邻居,每个方向一次。将节点访问的边存储为枚举 {up, down, left, right} 的最多 4 个条目。小于 90 x 4。

【讨论】:

  • 不在邻接矩阵中。您将只有一个非常稀疏的矩阵,但仍然是一个 90x90 矩阵(无论如何这都不是问题)
  • 没有要求使用邻接矩阵,也没有必要。
【解决方案2】:

一些可以帮助你决定你应该做什么的指针:

  1. 您的图表似乎未加权,因此您可以使用BFS,即 在这种情况下,比 Dijkstra 的算法更易于实现且更高效。
  2. 90x90 矩阵对于现代机器来说几乎不是问题(除非您要在非常紧凑的循环中使用寻路算法)
  3. 如果你使用double 作为权重,很多语言都有 您可以使用的无穷大值。在java中 Double.POSITIVE_INFINITY。关于无限的美 - 只要您添加它,它就会保持无限(并且不会像整数一样溢出)。
  4. 您始终可以使用adjacency lists,可以将其视为矩阵的稀疏实现 - 其中大多数边具有一些恒定的预定义权重(例如,对于不存在的边,无穷大)。
  5. 请注意,对于非常稀疏的图(如您的图)使用邻接矩阵而不是邻接列表会使 BFS 的时间复杂度 O(V^2) 而不是 O(V+E)(在您的情况下实际上是 O(V))和 O(V^2)对于 Dijkstra 的算法,而不是 O(E + VlogV)(您的图表是 O(VlogV)

【讨论】:

  • 这是有道理的(:我会考虑到所有这些!但是你能解释一下时间复杂度符号吗,例如 O(V^2) / O(V+E)?不是真的以前看过
  • @user3868416 实际上是 O(|V|^2) 和 O(|V|+|E|),我只是懒惰。 |V|是图中的顶点数,|E|是图中的边数。它有时被视为|V|=n|E|=m。在您的情况下,|E| < 4*|V||E|<8*|V| 如果您还允许对角线,那么 |E|本身在O(|V|)
【解决方案3】:

我同意 Rocky 的回答 - 只需将每个正方形的四个方向的权重存储在一个数组中(每个数组元素将是一个包含四个权重的结构/元组)。要查找两个任意正方形之间的边,首先检查它们是否相邻,如果是,则使用数组中的适当权重。不知道为什么有人提到邻接列表或矩阵,这在这里是多余的。

【讨论】:

    【解决方案4】:

    试试下面的代码来创建你的游戏。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
    
                object[,] input = {
                                   { 
                                       new object[] { 0, -1, -1,  1,  6}, //index, left, up, right, down
                                       new object[] { 1,  0, -1, -1,  7}, //index, left, up, right, down
                                       new object[] { 2, -1, -1,  3,  8}, //index, left, up, right, down
                                       new object[] { 3,  2, -1,  4,  9}, //index, left, up, right, down
                                       new object[] { 4,  3, -1, -1, 10}, //index, left, up, right, down
                                       new object[] { 5, -1, -1, -1, 11} //index, left, up, right, down 
                                   },
                                   { 
                                       new object[] { 6, -1,  0,  7, -1}, //index, left, up, right, down
                                       new object[] { 7,  6,  1, -1, 13}, //index, left, up, right, down
                                       new object[] { 8, -1,  2,  9, 14}, //index, left, up, right, down
                                       new object[] { 9,  8,  3, -1, -1}, //index, left, up, right, down
                                       new object[] {10, -1,  4, 11, -1}, //index, left, up, right, down
                                       new object[] {11, 10,  5, -1, 17} //index, left, up, right, down 
                                   },
                                   { 
                                       new object[] {12, -1, -1, 13, 19}, //index, left, up, right, down
                                       new object[] {13, 12,  7, 14, 20}, //index, left, up, right, down
                                       new object[] {14, 13,  8, 15, 21}, //index, left, up, right, down
                                       new object[] {15, 14, -1, -1, 22}, //index, left, up, right, down
                                       new object[] {16, -1, -1, 17, 23}, //index, left, up, right, down
                                       new object[] {17, 16, 11, -1, 24} //index, left, up, right, down 
                                   },
                                   { 
                                       new object[] {18, -1, 12, 19, 24}, //index, left, up, right, down
                                       new object[] {19, 18, 13, -1, 25}, //index, left, up, right, down
                                       new object[] {20, -1, 14, 21, 26}, //index, left, up, right, down
                                       new object[] {21, 20, 15, -1, 27}, //index, left, up, right, down
                                       new object[] {22, -1, 16, 23, 28}, //index, left, up, right, down
                                       new object[] {23, 22, 17, -1, 29} //index, left, up, right, down 
                                   },
                                   { 
                                       new object[] {24, -1, 18, 25, -1}, //index, left, up, right, down
                                       new object[] {25, 24, 19, 26, -1}, //index, left, up, right, down
                                       new object[] {26, -1, 20, 27, -1}, //index, left, up, right, down
                                       new object[] {27, 26, 21, 28, -1}, //index, left, up, right, down
                                       new object[] {28, 27, 22, 29, -1}, //index, left, up, right, down
                                       new object[] {29, 28, 23, -1, -1} //index, left, up, right, down 
                                   },
                               };
    
                cell game = new cell(input);
            }
        }
        public class cell
        {
            public static cell[,] board = new cell[5, 6];
    
            public int index { get; set; }  //row number * 6 + col 
            public int row { get; set;}
            public int col { get; set;}
            public cell up { get; set; }
            public cell down { get; set; }
            public cell left { get; set; }
            public cell right { get; set; }
    
            public cell() { }
    
            public cell(object[,] input)
            {
                int cellNumber = 0;
                int boardRow = 0;
                int boardCol = 0;
                int cellRow = 0;
                int cellCol = 0;
    
                for (int row = 0; row < 5; row++)
                {
                    for (int col = 0; col < 6; col++)
                    {
                        board[row, col] = new cell();
                    }
                }
    
                for (int row = 0; row < 5; row++)
                {
                    for (int col = 0; col < 6; col++)
                    {
                        object[] items = (object[])input[row, col];
                        cellNumber = (int)items[0];
                        boardRow = cellNumber / 6;
                        boardCol = cellNumber % 6;
    
                        board[boardRow, boardCol].index = cellNumber;
                        board[boardRow, boardCol].row = row;
                        board[boardRow, boardCol].col = col;
    
                        cellNumber = (int)items[1];
                        cellRow = cellNumber / 6;
                        cellCol = cellNumber % 6;
                        if (cellNumber == -1)
                        {
                            board[boardRow, boardCol].left = null;
                        }
                        else
                        {
                            board[boardRow, boardCol].left = board[cellRow, cellCol];
                        }                        
    
                        cellNumber = (int)items[2];
                        cellRow = cellNumber / 6;
                        cellCol = cellNumber % 6;
    
                        if (cellNumber == -1)
                        {
                            board[boardRow, boardCol].up = null;
                        }
                        else
                        {
                            board[boardRow, boardCol].up = board[cellRow, cellCol];
                        }                        
    
                        cellNumber = (int)items[3];
                        cellRow = cellNumber / 6;
                        cellCol = cellNumber % 6;
    
                        if (cellNumber == -1)
                        {
                            board[boardRow, boardCol].right = null;
                        }
                        else
                        {
                            board[boardRow, boardCol].right = board[cellRow, cellCol];
                        }                        
    
                        cellNumber = (int)items[4];
                        cellRow = cellNumber / 6;
                        cellCol = cellNumber % 6;
    
                        if (cellNumber == -1)
                        {
                            board[boardRow, boardCol].down = null;
                        }
                        else
                        {
                            board[boardRow, boardCol].down = board[cellRow, cellCol];
                        }                        
    
                    }
                }
            }
        }
    }
    ​
    

    【讨论】:

      【解决方案5】:

      使用此代码为大型数组初始化游戏板。然后为墙壁的位置添加空值,确保将墙壁添加到两个单元格。

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      
      namespace ConsoleApplication1
      {
          class Program
          {
              static void Main(string[] args)
              {
                  cell game = new cell(90, 100);
              }
          }
          public class cell
          {
              public static cell[,] board = null;
      
              public int index { get; set; }  //row number * 6 + col 
              public int row { get; set;}
              public int col { get; set;}
              public cell up { get; set; }
              public cell down { get; set; }
              public cell left { get; set; }
              public cell right { get; set; }
              public bool visited { get; set; }
      
              public cell() { }
      
              public cell(int rows, int cols)
              {
                  board = new cell[rows, cols];
                  int cellNumber = 0;
      
                  for (int row = 0; row < rows; row++)
                  {
                      for (int col = 0; col < cols; col++)
                      {
                          board[row, col] = new cell();
                          board[row, col].visited = false;
      
                      }
                  }
      
                  for (int row = 0; row < rows; row++)
                  {
                      for (int col = 0; col < cols; col++)
                      {
                          cellNumber = (row * cols) + col;
      
                          board[row, col].index = cellNumber;
                          board[row, col].row = row;
                          board[row, col].col = col;
      
                          if (col == 0)
                          {
                              board[row, col].left = null;
                          }
                          else
                          {
                              board[row, col].left = board[row, col - 1];
                          }                        
      
      
                          if (row == 0)
                          {
                              board[row, col].up = null;
                          }
                          else
                          {
                              board[row, col].up = board[row - 1, col];
                          }                        
      
      
                          if (col == cols - 1)
                          {
                              board[row, col].right = null;
                          }
                          else
                          {
                              board[row, col].right = board[row, col + 1];
                          }                        
      
                          if (row == rows - 1)
                          {
                              board[row, col].down = null;
                          }
                          else
                          {
                              board[row, col].down = board[row + 1, col];
                          }                        
      
                      }
                  }
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-13
        • 2011-01-26
        相关资源
        最近更新 更多