一、
问题描述:
A*算法是一种启发式图搜索算法,其特点在于对估价函数的定义上。对于一般的启发式图搜索,总是选择估价函数f值最小的节点作为扩展节点。因此,f是根据需要找到一条最小代价路径的观点来估算节点的,所以,考虑每个节点n的估价函数值为两个分量:f(n)=g(n)+h(n),从起始节点到节点n的实际代价g(n),从节点n到达目标节点的估价代价h(n)(不在点位个数),
八数码问题的求解
八数码问题是在3×3的九宫格棋盘上,摆有8个刻有1~8数码的将牌。棋盘中有一个空格,允许紧邻空格的某一将牌可以移到空格中,这样通过平移将牌可以将某一将牌布局变换为另一布局。给定的一种初始布局,目标状态,问如何移动将牌,实现从初始状态到目标状态的转变。
二、
算法设计:
将起始点加入open表
当open表不为空时:
寻找open表中f值最小的点current
它是终止点,则找到结果,程序结束。
否则,在Open表中移出current,对current表中的每一个临近点
若它不可走或在close表中,略过
若它不在open表中,加入。
若它在open表中,计算g值,若g值更小,替换其父节点为current,更新
它的g值。
若open表为空,则路径不存在。
算法流程图:
数据结构:用于记录最佳路径的树,两个链表,open表和close表
三、实现与实例
初始状态:2,8,3,0,6,4,1,7,5
目标状态:1,2,3,8,0,4,7,6,5
运行结果:
第0层的状态:
2 8 3
0 6 4
1 7 5
第1层的状态:
2 8 3
1 6 4
0 7 5
第2层的状态:
2 8 3
1 6 4
7 0 5
第3层的状态:
2 8 3
1 0 4
7 6 5
第4层的状态:
2 0 3
1 8 4
7 6 5
第5层的状态:
0 2 3
1 8 4
7 6 5
第6层的状态:
1 2 3
0 8 4
7 6 5
第7层的状态:
1 2 3
8 0 4
7 6 5
生成节点数目:20
扩展节点数目:10
运行时间:16.000000
代码实现:
#include "iostream"
#include "stdlib.h"
#include "conio.h"
#include <math.h>
#include <windows.h>
using namespace std;
//定义二维数组来存储数据表示某一个特定状态
typedef int status[3][3];
//定义 状态图中的结点数据结构
typedef struct Node
{
status data;//结点所存储的状态 ,一个3*3矩阵
struct Node* parent;//指向结点的父亲结点
struct SpringLink* child;//指向结点的后继结点
struct Node* next;//指向open或者closed表中的后一个结点
int fvalue;//结点的估价函数值
int gvalue;//结点的深度
int hvalue;//结点到目标节点的预估代价值
}NNode, * PNode;
//定义存储指向结点后继结点的指针的地址
typedef struct SpringLink
{
struct Node* pointData;//指向结点的指针
struct SpringLink* next;//指向兄第结点
}SPLink, * PSPLink;
PNode open;
PNode closed;
//OPEN表保存所有已生成而未考察的节点,CLOSED表中记录已访问过的节点
//开始状态与目标状态
int t = 0; //迭代次数,相当于运行时间
int count_extendnode = 0;//扩展结点
int count_sumnode = 0; //生成节点
status startt = { 2,8,3,0,6,4,1,7,5 }; //实验报告
status target = { 1,2,3,8,0,4,7,6,5 };
//初始化空链表
void initLink(PNode& Head)
{
Head = (PNode)malloc(sizeof(NNode));
Head->next = NULL;
}
//判断链表是否为空
bool isEmpty(PNode Head)
{
if (Head->next == NULL)
return true;
else
return false;
}