八数码问题C语言A星算法详细实验报告含代码
- 格式:doc
- 大小:224.50 KB
- 文档页数:10
一、实验内容与要求八数码问题:在3×3的方格棋盘上,摆放着1到8这八个数码,有1个方格就是空的,其初始状态如图1所示,要求对空格执行空格左移、空格右移、空格上移与空格下移这四个操作使得棋盘从初始状态到目标状态。
例如:图1 八数码问题示意图请任选一种盲目搜索算法(广度优先搜索或深度优先搜索)或任选一种启发式搜索方法(全局择优搜索,加权状态图搜索,A 算法或A* 算法)编程求解八数码问题(初始状态任选)。
选择一个初始状态,画出搜索树,填写相应的OPEN表与CLOSED表,给出解路径,对实验结果进行分析总结,得出结论。
二、实验目的1、熟悉人工智能系统中的问题求解过程;2、熟悉状态空间的盲目搜索与启发式搜索算法的应用;3、熟悉对八数码问题的建模、求解及编程语言的应用。
三、实验算法A*算法就是一种常用的启发式搜索算法。
在A*算法中,一个结点位置的好坏用估价函数来对它进行评估。
A*算法的估价函数可表示为:f'(n) = g'(n) + h'(n)这里,f'(n)就是估价函数,g'(n)就是起点到终点的最短路径值(也称为最小耗费或最小代价),h'(n)就是n到目标的最短路经的启发值。
由于这个f'(n)其实就是无法预先知道的,所以实际上使用的就是下面的估价函数:f(n) = g(n) + h(n)其中g(n)就是从初始结点到节点n的实际代价,h(n)就是从结点n到目标结点的最佳路径的估计代价。
在这里主要就是h(n)体现了搜索的启发信息,因为g(n)就是已知的。
用f(n)作为f'(n)的近似,也就就是用g(n)代替g'(n),h(n)代替h'(n)。
这样必须满足两个条件:(1)g(n)>=g'(n)(大多数情况下都就是满足的,可以不用考虑),且f必须保持单调递增。
(2)h必须小于等于实际的从当前节点到达目标节点的最小耗费h(n)<=h'(n)。
第二点特别的重要。
可以证明应用这样的估价函数就是可以找到最短路径的。
3、A*算法的步骤A*算法基本上与广度优先算法相同,但就是在扩展出一个结点后,要计算它的估价函数,并根据估价函数对待扩展的结点排序,从而保证每次扩展的结点都就是估价函数最小的结点。
A*算法的步骤如下:1)建立一个队列,计算初始结点的估价函数f,并将初始结点入队,设置队列头与尾指针。
2)取出队列头(队列头指针所指)的结点,如果该结点就是目标结点,则输出路径,程序结束。
否则对结点进行扩展。
3)检查扩展出的新结点就是否与队列中的结点重复,若与不能再扩展的结点重复(位于队列头指针之前),则将它抛弃;若新结点与待扩展的结点重复(位于队列头指针之后),则比较两个结点的估价函数中g的大小,保留较小g值的结点。
跳至第五步。
4)如果扩展出的新结点与队列中的结点不重复,则按照它的估价函数f大小将它插入队列中的头结点后待扩展结点的适当位置,使它们按从小到大的顺序排列,最后更新队列尾指针。
5)如果队列头的结点还可以扩展,直接返回第二步。
否则将队列头指针指向下一结点,再返回第二步。
四、程序框图五、实验结果及分析输入初始状态:2 8 3 目标状态: 1 2 31 6 4 8 0 47 0 5 7 6 5运行结果屏幕打印OPEN表与CLOSE表:OPEN CLOSE1 2 3 4 02 3 4 5 6 0 12 3 4 6 7 0 1 52 3 4 6 8 9 0 1 5 72 3 4 8 9 10 0 1 5 7 62 3 4 8 11 12 13 0 1 5 7 6 92 3 4 8 12 13 14 15 0 1 5 7 6 9 113 4 8 12 13 14 15 16 17 0 1 5 7 6 9 11 24 8 12 13 14 15 16 17 18 19 0 1 5 7 6 9 11 2 34 8 12 13 14 15 16 17 19 20 0 1 5 7 6 9 11 2 3 188 12 13 14 15 16 17 19 21 22 0 1 5 7 6 9 11 2 3 18 412 13 14 15 16 17 19 21 22 23 0 1 5 7 6 9 11 2 3 18 4 812 13 14 15 16 17 19 21 22 24 25 0 1 5 7 6 9 11 2 3 18 4 8 2312 13 14 15 16 17 19 21 22 24 26 0 1 5 7 6 9 11 2 3 18 4 8 23 24发现26为目标节点搜索树:0…7 2 8 3 1 0 4 7 6 5六、结论对于八数码问题,BFS算法最慢,A*算法较快。
八数码问题的一个状态实际上就是0~9的一个排列,对于任意给定的初始状态与目标,不一定有解,也就就是说从初始状态不一定能到达目标状态。
因为排列有奇排列与偶排列两类,从奇排列不能转化成偶排列。
如果一个数字0~8的随机排列871526340,用F(X)表示数字X前面比它小的数的个数,全部数字的F(X)之与为Y=∑(F(X)),如果Y为奇数则称原数字的排列就是奇排列,如果Y为偶数则称原数字的排列就是偶排列。
因此,可以在运行程序前检查初始状态与目标状态的排序的奇偶行就是否相同,相同则问题可解,应当能搜索到路径。
否则无解。
七、源程序及注释#include <iostream>#include <ctime>#include <vector>using namespace std;const int ROW = 3;const int COL = 3;const int MAXDISTANCE = 10000;const int MAXNUM = 10000;int abs(int a){if (a>0) return a;else return -a;}typedef struct _Node{int digit[ROW][COL];int dist; // 距离int dep; // 深度int index; // 索引值} Node;Node src, dest;vector<Node> node_v; // 储存节点bool isEmptyOfOPEN() { //判断Open表就是否空for (int i = 0; i < node_v、size(); i++) {if (node_v[i]、dist != MAXNUM)return false;}return true;}bool isEqual(int index, int digit[][COL]) { //判断节点就是否与索引值指向的节点相同for (int i = 0; i < ROW; i++)for (int j = 0; j < COL; j++) {if (node_v[index]、digit[i][j] != digit[i][j])return false;}return true;}ostream& operator<<(ostream& os, Node& node) {for (int i = 0; i < ROW; i++) {for (int j = 0; j < COL; j++)os << node、digit[i][j] << ' ';os << endl;}return os;}void PrintSteps(int index, vector<Node>& rstep_v) { //输出步骤rstep_v、push_back(node_v[index]);index = node_v[index]、index;while (index != 0) {rstep_v、push_back(node_v[index]);index = node_v[index]、index;}for (int i = rstep_v、size() - 1; i >= 0; i--)cout << "Step " << rstep_v、size() - i<< endl << rstep_v[i] << endl;}void S a, int& b) { //交换int t;t = a;a = b;b = t;}void Assign(Node& node, int index) { //获取节点for (int i = 0; i < ROW; i++)for (int j = 0; j < COL; j++)node、digit[i][j] = node_v[index]、digit[i][j];}int GetMinNode() { //获取启发值最小的节点int dist = MAXNUM;int loc; // the location of minimize nodefor (int i = 0; i < node_v、size(); i++) {if (node_v[i]、dist == MAXNUM)continue;else if ((node_v[i]、dist + node_v[i]、dep) < dist) { loc = i;dist = node_v[i]、dist + node_v[i]、dep;}}return loc;}bool isExpandable(Node& node) { //判断就是否可扩展for (int i = 0; i < node_v、size(); i++) {if (isEqual(i, node、digit))return false;}return true;}int Distance(Node& node, int digit[][COL]) { //计算距离int distance = 0;bool flag = false;for(int i = 0; i < ROW; i++)for (int j = 0; j < COL; j++)for (int k = 0; k < ROW; k++) {for (int l = 0; l < COL; l++) {if (node、digit[i][j] == digit[k][l]) { distance += abs(i - k) + abs(j - l);flag = true;break;}elseflag = false;}if (flag)break;}return distance;}int MinDistance(int a, int b) { //二者取小return (a < b ? a : b);}void ProcessNode(int index) { //展开节点int x, y;bool flag;for (int i = 0; i < ROW; i++) {for (int j = 0; j < COL; j++) {if (node_v[index]、digit[i][j] == 0) {x =i; y = j;flag = true;break;}else flag = false;}if(flag)break;}Node node_up; //上移操作Assign(node_up, index);int dist_up = MAXDISTANCE;if (x > 0) {S[x][y], node_up、digit[x - 1][y]);if (isExpandable(node_up)) {dist_up = Distance(node_up, dest、digit); node_up、index = index;node_up、dist = dist_up;node_up、dep = node_v[index]、dep + 1;node_v、push_back(node_up);}}Node node_down; //下移操作Assign(node_down, index);int dist_down = MAXDISTANCE;if (x < 2) {S[x][y], node_down、digit[x + 1][y]);if (isExpandable(node_down)) {dist_down = Distance(node_down, dest、digit); node_down、index = index;node_down、dist = dist_down;node_down、dep = node_v[index]、dep + 1;node_v、push_back(node_down);}}Node node_left;//左移操作Assign(node_left, index);int dist_left = MAXDISTANCE;if (y > 0) {S[x][y], node_left、digit[x][y - 1]);if (isExpandable(node_left)) {dist_left = Distance(node_left, dest、digit); node_left、index = index;node_left、dist = dist_left;node_left、dep = node_v[index]、dep + 1;node_v、push_back(node_left);}}Node node_right; //右移操作Assign(node_right, index);int dist_right = MAXDISTANCE;if (y < 2) {S[x][y], node_right、digit[x][y + 1]);if (isExpandable(node_right)) {dist_right = Distance(node_right, dest、digit); node_right、index = index;node_right、dist = dist_right;node_right、dep = node_v[index]、dep + 1;node_v、push_back(node_right);}}node_v[index]、dist = MAXNUM;}int main() {int number;cout << "输入初始状态:" << endl;for (int i = 0; i < ROW; i++)for (int j = 0; j < COL; j++) {cin >> number;src、digit[i][j] = number;}src、index = 0;src、dep = 1;cout << "输入目标状态" << endl;for (int m = 0; m < ROW; m++)for (int n = 0; n < COL; n++) {cin >> number;dest、digit[m][n] = number;}node_v、push_back(src);while (1) {if (isEmptyOfOPEN()) {cout << "找不到解!" << endl;return -1;}else {int loc; // the location of the minimize node loc = GetMinNode();if(isEqual(loc, dest、digit)) {vector<Node> rstep_v;cout << "初始状态:" << endl;cout << src << endl;PrintSteps(loc, rstep_v);cout << "成功!" << endl;break;}elseProcessNode(loc);}}return 0;}。