我编写了一个使用A *算法来解决N-Puzzle的程序。该算法运行良好,但与使用相同算法解决相同问题的所有程序相比,它似乎非常慢。 我认为减慢我的代码的部分是在打开和关闭列表中检查新节点是否存在时。 基本上我正在做的是检查特定节点的整个值数组,每个节点存储在Closed和open列表中。 以下是我认为导致速度减慢的代码段。
for(auto temp_Node:Neighbours(process))
{
auto pred = [temp_Node](Node* item) //lambda Expression for 'pred', custom comparator
{
bool value=true;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
{
if(item->Grid[i][j]!=temp_Node->Grid[i][j])
{
value=false;
break;
}
}
if(item->g!=temp_Node->g)
value=false;
return value;
};
if(find_if(begin(closed_list),end(closed_list), pred)==end(closed_list))
{
auto open_list_cpy=find_if(begin(open_list),end(open_list), pred);
if(open_list_cpy==open_list.end())
{
open_list.insert(temp_Node);
}
正如您所看到的,我正在使用带有find_if的lambda表达式来检查每个节点中的所有值。
我想知道我是否遗漏了某些东西,或者是否有其他更有效的方法来解决这个问题,或者这是怎么做的,我的代码的其他部分有问题?
答案 0 :(得分:1)
您可能希望使用网格保留map
或set
个节点以进行比较,而不是按顺序搜索所有节点:
struct GridLess {
bool operator()(const Node *a,const Node *b) const
{
assert(a);
assert(b);
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
if(a->Grid[i][j]!=b->Grid[i][j])
{
return a->Grid[i][j] < b->Grid[i][j];
}
}
}
return false;
}
};
std::set<Node*,GridLess> closed_list;
现在你可以使用
if (closed_list.count(temp_Node)==0) {
// No node in closed_list has the same grid as temp_node
}
这将时间复杂度从O(n)减少到O(log(n))。