【发布时间】:2011-12-09 18:41:27
【问题描述】:
我正在用 C++ 实现 A* algorithm 来解决 n-puzzle 问题。
我尝试在this 链接中实现伪代码。
总成本(F=H+G)的计算是“成本取决于错位瓷砖的数量(启发式)+初始状态的步骤(G)”。下面给出了AStar 函数的算法。
问题是,我遇到了无限循环的情况。我该如何解决这个问题?
PS:如果需要,我可以提供AStar 中使用的其他功能的实现。
任何帮助将不胜感激。
void AStar(const int size, int** puzzle)
{
int moveCount = 0; // initialize G(n)
int**goalState = GoalState(size); // initialize and assign goal state
int openListIndex = 0; // initialize open list index
vector<node> openList; // initialize open list
vector<node> closedList; // initialize closed list
node startNode; // initialize start node
startNode.puzzleArray = puzzle; // assign start node's state
startNode.cost = moveCount + Heuristics(goalState,puzzle,size); // assign start node's cost
node goalNode; // initialize goal node
goalNode.puzzleArray = goalState; // assign goal node's state
openList.push_back(startNode); // push start node to the open list
while (!openList.empty()) // loop while open list is not empty
{
node currentNode = CalculateLowestCost(&openList, &closedList); // initialize current node which has the lowest cost, pop it from open list, push it to the closed list
int** currentState = currentNode.puzzleArray; // initialize and assign current state array
/*********************************************************************************************/
if (GoalCheck(goalState, currentState, size)) break; // GOAL CHECK//
/*********************************************************************************************/
vector<char> successorDirectionList = CalculateSuccessor(size, currentState); // initialize a char vector for the directions of the successors
int**successor; // initialize successor state
node successorNode; // initialize successor node
moveCount++; // advance G(n)
for (;!successorDirectionList.empty();) // loop over the successor list
{
char direction = successorDirectionList.back(); // take a direction from the list
successorDirectionList.pop_back(); // remove that direction from the list
successor = MoveBlank(currentState, size, direction); // assign successor state
successorNode.puzzleArray = successor; // assign successor node's state
successorNode.cost = moveCount + Heuristics(goalState,currentState,size); // assign successor node's cost
//vector<node> stateCheckList = openList; // copy the open list for the checking the nodes in that list
bool flagOpen = false;
bool flagClosed = false;
int locationOpen = -1;
int locationClosed = -1;
for (int i=0; i<openList.size(); i++)
{
int** existing = openList[i].puzzleArray;
int existingCost = openList[i].cost;
if (StateCheck(successor, existing, size))
{
locationOpen = i;
if (successorNode.cost > existingCost)
{
flagOpen = true;
break;
}
}
}
if (flagOpen) continue;
int** existingInOpen;
if(locationOpen != -1)
{
existingInOpen = openList[locationOpen].puzzleArray;
openList.erase(openList.begin()+locationOpen);
}
for (int i=0; i<closedList.size(); i++)
{
int** existing = closedList[i].puzzleArray;
int existingCost = closedList[i].cost;
if (StateCheck(successor, existing, size))
{
locationClosed = i;
if (successorNode.cost > existingCost)
{
flagClosed = true;
break;
}
}
}
if (flagClosed) continue;
int**existingInClosed;
if(locationClosed != -1)
{
existingInClosed = closedList[locationClosed].puzzleArray;
closedList.erase(closedList.begin()+locationClosed);
}
openList.push_back(successorNode);
}
}
}
【问题讨论】:
-
更多的是一个问题而不是评论,但你为什么不在你有'for (;!successorDirectionList.empty();)'的地方使用'while (!successorDirectionList.empty())'?虽然你所做的当然是合法的语法,但它并不完全是典型的。
-
我以为是一样的,有什么区别呢?在你说之后我尝试了“while”,但仍然进入无限循环。
-
是一回事;这不是人们通常使用的。
-
一些额外的信息也可能有用:你怎么知道有一个无限循环(而不是一个正在进行但需要很长时间的循环)?您执行了哪些测试来验证是否存在无限循环,它是哪个循环?你如何设置问题开始? IIRC,如果你从一个纯粹的随机状态开始,有些配置是无法解决的。
-
我正在使用 3x3 板(8 拼图)进行测试,使用这种“可接受的”启发式算法,最多只能走 22 步(我认为)。顺便说一句,正如我现在测试的那样,当涉及到 2x2 时,它并没有给出无限循环。
标签: c++ heuristics a-star sliding-tile-puzzle