题目链接:P1379 八数码难题
题目大意: 要求最少步骤的移动方法,实现从初始布局到目标布局的转变。
解题思路: 这道题目要用到搜索中比较难的搜索方法—迭代加深的A*算法。所谓迭代加深就是每次限制搜索深度, 这样可以在整个搜索树深度很大而答案深度又很小的情况下大大提高效率。使maxdep从1开始不断加深枚举, 作为最大步数进行迭代加深搜索判断,而对于不用移动的情况可以一开始直接特判。在这里我们的A*估价函数设置为当前状态还有多少个位置与目标状态不对应。这只是我们预估现在的状态到目标状态的距离,我们预想的距离一定是比实际距离短,或者刚好等于实际距离的值(因为这是我们每一步都走正确的预估步数)。若当前步数+估价函数值>枚举的最大步数 则直接返回(现在花费的步数+预估的步数>=现在花费的步数+实际花费的步数,也就是超出了最大的步数)。当然这只是基本思路,搜索还可以有很大优化。我们在搜索中再加入最优性剪枝, 显然当前枚举下一个状态时如果回到上一个状态肯定不是最优, 所以我们在枚举下一状态时加入对这种情况的判断。将状态数组对称化可以实现这一操作:
const int dx[] = {
0,1,-1,0 };
const int dy[] = {
1,0,0,-1 };
索引0和3对称,索引1和2对称。
if (i == 3 - pre||!isValid(tx,ty)) {
continue;
}
i是现在的状态,pre是上一个状态,如果i+pre==3,则说明我们枚举下一个状态时回到了上一个状态。(比如说上一次我向右走,这一次向左走,就回到了出发点,肯定不是最优解)。
参考文章: A*算法和启发性搜索
代码:
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 5000;
const int goal[4][4] =
{
{