1 问题描述
3×3九宫棋盘,放置数码为1-8的8个棋牌,剩下一个空格,只能通过棋牌向空格的移动来改变棋盘的布局。要求:根据给定初始布局(即初始状态)和目标布局(即目标状态),如何移动棋牌才能从初始布局到达目标布局,找到合法的走步序列。
图1 求解过程示例
2 求解算法设计
2.1算法原理分析
本次实验采用了启发式搜索算法来求解八数码问题。其基本思想是从根节点拓展出子节点,然后从所有未拓展过的节点中选出代价最小的节点,并拓展该节点。然后继续从所有未拓展过的节点中选出代价最小的节点并拓展,循环调用这个步骤直到找到目标节点。
启发函数h(n):当前节点与目标节点格局相比,位置不符的数字移动到目标节点中对应位置的最短距离之和。
图2 全局择优搜索过程示例
2.2算法步骤设计
○1读取初始状态和目标状态,并判断二者能否通过变换到达。
○2将初始节点压入OPEN表
○3取出OPEN表中估计值最小的节点,并放入CLOSE表
○4如果该节点不是目标节点,扩展该节点,将子节点放入OPEN表,并返回到第三步。
○5将该节点压入栈中,并将指针指向其父节点。
○6如果该节点的父节点不为空,返回到第五步。
○7如果栈不为空,出栈并输出该节点,直到栈为空。
#include<queue>
#include<iostream>
#include "stdlib.h"
#include "time.h"
#include<stack>
using namespace std;
#define num 9
struct Node{
int state[9];
struct Node* parent;
int value;
int depth;
friend bool operator < (Node A, Node B) //按照value值小的方案构造优先级队列
{
return A.value > B.value;
}
};
priority_queue<Node> openTable; //open表
queue<Node> closeTable; //close表
stack<Node> Path; //最终路径
int count1=0,count2=0;
int read(Node& S,Node& G){
/*初始化*/
S.parent=NULL; S.depth=0; S.value=0;
G.parent=NULL; G.depth=0; G.value=0;
cout<<"请输入初始状态\n";
for(int i=0;i<num;i++)
cin>>S.state[i];
cout<<"请输入目标状态?\n";
for(int i=0;i<num;i++)
cin>>G.state[i];
for(int i=0;i<=num-2;i++)
for(int j=i+1;j<num;j++)
if(S.state[i]>S.state[j