A* 寻路速度慢
A* pathfinding slow
我目前正在研究A*搜索算法。该算法只是解决文本文件迷宫。我知道 A* 算法应该非常快速地找到完成。我的似乎需要 6 秒才能在没有墙壁的 20x20 迷宫中找到路径。它确实找到了正确的路径,只需要永远这样做。
如果我知道代码的哪一部分是问题所在,我会发布它,但我真的不知道出了什么问题。所以这是我使用的算法...
while(!openList.empty()) {
visitedList.push_back(openList[index]);
openList.erase(openList.begin() + index);
if(currentCell->x_coor == goalCell->x_coor && currentCell->y_coor == goalCell->y_coor)
}
FindBestPath(currentCell);
break;
}
if(map[currentCell->x_coor+1][currentCell->y_coor] != wall)
{
openList.push_back(new SearchCell(currentCell->x_coor+1,currentCell->y_coor,currentCell));
}
if(map[currentCell->x_coor-1][currentCell->y_coor] != wall)
{
openList.push_back(new SearchCell(currentCell->x_coor-1,currentCell->y_coor,currentCell));
}
if(map[currentCell->x_coor][currentCell->y_coor+1] != wall)
{
openList.push_back(new SearchCell(currentCell->x_coor,currentCell->y_coor+1,currentCell));
}
if(map[currentCell->x_coor][currentCell->y_coor-1] != wall)
{
openList.push_back(new SearchCell(currentCell->x_coor,currentCell->y_coor-1,currentCell));
}
for(int i=0;i<openList.size();i++) {
openList[i]->G = openList[i]->parent->G + 1;
openList[i]->H = openList[i]->ManHattenDistance(goalCell);
}
float bestF = 999999;
index = -1;
for(int i=0;i<openList.size();i++) {
if(openList[i]->GetF() < bestF) {
for(int n=0;n<visitedList.size();n++) {
if(CheckVisited(openList[i])) {
bestF = openList[i]->GetF();
index = i;
}
}
}
}
if(index >= 0) {
currentCell = openList[index];
}
}
我知道这段代码很混乱,不是最有效的做事方式,但我认为它仍然应该比它更快。任何帮助将不胜感激。
谢谢。
> 您的 20x20 迷宫没有墙壁,因此许多路线的长度都相同。事实上,我估计有数万亿条等效路线。当你考虑到这一点时,它似乎并没有那么糟糕。
当然,由于您的启发式方法看起来很完美,因此排除启发式预测的路线与迄今为止已知的最佳路线一样长,您应该会获得很大的好处。(如果您的启发式是正确的,这是安全的,即永远不要高估剩余距离)。
这是一个很大的提示。
如果你找到两条通往同一牢房的路径,你总是可以扔掉更长的一条。 如果有领带,你可以扔掉第二个到达那里。
如果您实现这一点,没有其他优化,搜索将变得非常快。
其次,A* 算法应该只在当前单元格加上启发式的长度超过当前单元格加上任何其他节点的启发式的长度时进行回溯。 如果你实现了这一点,那么它应该直接找到一条路径并停止。 为了方便起见,您需要将路径存储在优先级队列(通常使用堆实现)中,而不是向量中。
openList.erase
是 O(n),而以 for(int i=0;i<openList.size();i++)
开头的 for 循环是 O(n^2),因为调用了 CheckVisited
- 这些每次迭代都会调用,使您的整体算法 O(n^3)。 A* 应为 O(n log n)。
尝试将openList
更改为优先级队列,并将其visitedList
更改为哈希表。 然后,整个for
循环可以用dequeue
替换 - 确保在排队前检查是否visitedList.Contains(node)
!
此外,无需在每次迭代时重新计算每个节点的ManHattenDistance
,因为它永远不会更改。
你不是经常回溯吗?
当当前最佳解决方案变得比之前访问过的另一个路由更差时,A* 算法会回溯。在你的情况下,由于没有墙壁,所以所有路线都是好的,永远不会死(正如MSalters正确指出的那样,有几条)。当你迈出一步时,你的路线会变得比其他所有短一步的路线更糟糕。
如果这是真的,这可能解释了你的算法所花费的时间。
- CUDA Shuffle指导减少速度慢于减少共享记忆
- 使用boost.lockfree队列比使用静音速度慢
- 具有3D障碍物的寻路
- 提升文件系统的速度慢得令人难以置信
- Winsock C++ - Java 连接速度慢
- Qt自定义树模型显示正确,但有缺陷且速度慢
- 一种在没有光线投射的情况下在 3D 中使用寻路和多目标的方法
- 为什么我的沿航点寻路的算法不起作用
- C++线程化的应用程序比非线程化的运行速度慢
- 函数调用速度慢得令人痛苦
- gcc std::unordered_map 实施速度慢吗?如果是这样 - 为什么
- 返回元素的速度比通过引用和修改发送元素的速度慢
- 查找相邻节点 星形寻路C++
- A* 寻路速度慢
- 使用递归在C++中寻路
- 流网络摄像头的速度慢,无法"detectMultiScale"
- 网格系统中的寻路
- 相同的功能?使用 GMP(C++) 时运行速度慢约 10 倍
- C++ 多线程处理速度慢
- C++ ifstream::由于memcpy,读取速度慢