问题描述:在 3x3 的棋盘上放有8个棋子,分别用1~8表示。有一个空格,附近的棋子可以移动到空格的位子上,用0表示。给出一个初始状态,从初始状态到123456780需要的最小步数。
问题分析:大部分人关注的点在于将空格附近的哪个棋子移动到空格上,然而真正清晰的关注点应该是将空格移动到附近的哪个位置。
问题本质:图上的最短路径问题。(普通的最短路径问题是由一个起始点到达某个目标点。该问题的最短路径是由一个起始点(空格)经过移动,形成某种目标状态)。
基于以上思想,我们可以很方便地将该问题转化为最短路径问题BFS。
问题的注意事项:
状态的表示:状态很好找,每次移动空格就会形成一种新的状态。
判重:给每一种状态一个标记bool,有9!种状态,用来表示当前状态是否经历过。是一种int和bool的映射关系。可以直接使用STL中的map集合。
算法的优化(启发式搜索 A*):为了使算法运行的速度更快,我们需要对算法进行优化,避免算法走更多的弯路。
因为我们要求出从初始状态到目标状态的最大号的移动次数,所以,我们优先探查那些最容易达到目标状态的状态。我们使用**估价函数f(n)=g(n)+h(n)**对状态进行排序(启发式策略)。其中g(n)为从初始状态到当前状态的步数,h(n)为当前状态节点“不在位”的棋子数。