我应该在不基于网格的 A* 算法中存储 2d 点之间的距离吗

Should I store distances between 2d points in a not grid based A* algorithm

我正在实现 A* 算法。任何节点都可以连接到任何其他节点,前提是没有任何东西阻碍路径,这种情况很少见。通过这种方式找到的路径通常包含少量节点(甚至可能只有 2 个),但是从一个节点移动到另一个节点的选项非常多。在基于网格的 A* 算法视频中,我听说存储这些距离而不是一遍又一遍地计算它们是个好主意,但这里是这种情况吗?节点的位置未绑定到网格,在我看来,计算距离的字典会变得太大而无法使用(搜索键)。节点不应该太多(30到500),那么字典中查找对应值的499次引用比较,会不会比每次只计算距离耗时更长?如果不是——这个字典搜索时间对多少节点有影响? 下面是我使用的 class 的框架代码。

class Node
{
    private Vector2 position;
    public Vector2 Position 
    {
        get 
        {
            return position;
        }
        set 
        {
            position = value; 
            calculatedDistances.Clear();
        }
    }
    private Dictionary<Node, float> calculatedDistances;

    public float DistanceTo(Node to)
    {
        float dist;
        if (calculatedDistances.TryGetValue(to, out dist))
        {
            return dist;
        }
        else
        {
            dist = Vector2.Distance(this.Position, to.Position);
            calculatedDistances.Add(to, dist);
            return dist;
        }
    }
}

性能特征在很大程度上取决于您的实际数据集。您几乎不应该依赖您认为 会更快的东西:profile profile profile。 C# Stopwatch class 非常适合这个目的。

话虽这么说,这里有一些关于您的案例的想法:

  • 字典可能不会进行 499 次参考比较。根据 C# 字典的具体实现(根据 MSDN,它使用散列 table),您可以接近 O(1) 查找,而不是 O(n)(对于线性扫描)或 O( log(n)) (用于二进制搜索)。
  • 使用 A*,您不需要使用节点之间的实际距离。任何充当 "metric" 的东西都可以。为了成为一个度量,它只需要始终为正(除非你比较相同的两个点,在这种情况下它必须为 0)并且从 A -> B -> C 的距离必须大于或等于A -> C。具体来说,您可以使用距离的平方,而不是距离。当您关心性能时,这可以为您节省昂贵的平方根计算。