重排九宫(广度优先算法)
问题描述
重排九宫问题:在 3*3 的方格棋盘上放置分别标有数字 1,2,3,4,5,6,7,8 的 8 张牌,初始状态为 s_0,目标状态 为s_g,可使用的算符有空格左移,空格上移,空格右移和空格下移,即它们只允许把位于 空格左,上,右,下边的牌移入空格。要求寻找从初始状态到目的状态的路径。
可以下载全部代码
算法描述
采用了广度优先算法(部分改进),在加入子节点的时候将其按照代价函数从小到大排序,在检测之前是否出现时使用了哈希表,将九个数连起来的数作为该状态在哈希表中的位置,如果出现过设为1
实验结果
主要代码
1.主要流程
void Solution(Node start, Node target)
{
int j = 0, c = 0;
while (1)
{
if (k == m)
{
cout << "无解" << endl;
break;
}
if (ifTarget(Open[k], target))//是否是目标结点
{
Node solution[100];
int i = 0, j = 0, q;
cout << "solution:" << endl;
while (Open[k].father != -1)
{
solution[i] = Open[k];
Open[k] = Open[Open[k].father];
i++;
}
q = i;
cout << "step 0" << endl;
start.show();
for (i = q - 1;i >= 0;i--)
{
j++;
cout << "step " << j << endl;
solution[i].show();
}
//cout << "Solve!" << endl;
break;
}
j = getZeroLocation(Open[k]);//0的位置
changeOpen(Open[k], j);
k++;
c++;
}
}
2.代价函数
void Node::setEva()
{
int i, temp = 0;
for (i = 0;i < 9;i++)
if (state[i] != tgt[i])
temp++;
difference = temp;
eva = difference + depth;//启发函数值
}
3.节点类
//节点类
class Node
{
public:
int state[9];
int father;//父结点编号
int difference;//与目标的差异
int depth;//深度
int eva;//代价
int loc;//在hsTable表位置
Node();
void show();
void setEva();
void setState(int a[9]);
void setLoc();
};
改进建议
这个使用了广度优先算法,在加子节点的时候使用了局部优先算法,但还是效率有点低,在排序的时候自己比较了各种情况,也有点复杂,可以用优先队列来实现,更加简洁,A*算法也由此容易实现。还有输出结果的时候逻辑有点乱,但是输出成功了就没再管。????