- 1、本文档共10页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
启发式搜索八数码问题
启发式搜索
介绍
八数码问题也称为九宫问题。在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同。棋盘上还有一个空格,与空格相邻的棋子可以移到空格中。要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤。所谓问题的一个状态就是棋子在棋盘上的一种摆法。解八数码问题实际上就是找出从初始状态到达目标状态所经过的一系列中间过渡状态。
使用启发式搜索算法求解8数码问题。采用估价函数
,其中:是搜索树中结点的深度;为结点的数据库中错放的棋子个数;为结点的数据库中每个棋子与其目标位置之间的距离总和。宽度搜索采用f(i)为
算法流程
把起始节点SOPEN表中,并计算节点S的;
如果OPEN是空表,则失败退出,无解;
从OPEN表中选择一个值最小的节点。如果有几个节点值相同,当其中有一个
为目标节点时,则选择此目标节点;否则就选择其中任一个节点作为节点;
把节点OPEN 表中移出,并把它放入 CLOSED 的已扩展节点表中;
如果是个目标节点,则成功退出,求得一个解;
扩展节点,生成其全部后继节点。对于的每一个后继节点:
计算;如果 既不在OPEN表中,又不在CLOCED表中,则用估价函数把
它添入OPEN表中。从加一指向其父节点的指针,以便一旦找到目标节点时记住一个解答路径;如果已在OPEN表或CLOSED表中,则比较刚刚对计算过的和前面计算过的该节点在表中的值。如果新的较小,则
(I)以此新值取代旧值。
(II)从指向,而不是指向他的父节点。
(III)如果节点在CLOSED表中,则把它移回OPEN表中。
转向②,即GOTO②。
估价函数
计算一个节点的估价函数,可以分成两个部分:n的估价函数定义为从初始节点、经过n、到达目标节点的路径的最小代价的估计值,即 = + 。
是从初始节点到达当前节点n的实际代价;
是从节点n到目标节点的最佳路径的估计代价,体现出搜索过程中采用的启发式信息(背景知识),称之为启发函数。
所占的比重越大,越趋向于宽度优先或等代价搜索;反之,的比重越大,表示启发性能就越强。
实验代码
为方便起见目标棋局为
(1)以下代码估价函数为深度+错放棋子个数
(2) 若估价函数为深度+每个棋子与其目标位置之间的距离总和,则加入估价函数
int calvalue1(int a[]) //不在位棋子数
{
int c = 0;
int b=0;
for (int i = 0;i = 8;i++)
for (int j = 0;j = 8;j++)
if (a[i] = goal[j])
if (goal[j] != 0)
c=c+abs(i%3-j%3)+abs((i- i%3)/3+(j- j%3)/3);
return c;
}
(3)宽度搜索采用OPEN-jiedian.f = depth;
(4) 深度搜索采用OPEN-jiedian.f = -depth;
源代码:
#include stdio.h
int goal[9] = { 1,2,3,8,0,4,7,6,5 }, sgoal[9];//goal为棋盘的目标布局,并用中间状态sgoal与之比较
struct Board
{
int shuzu[9];
int d, f, e;//d:深度;f:启发函数;e:记录前一次的扩展节点
};
struct NodeLink
{
Board jiedian;
NodeLink *parent;
NodeLink *previous;
NodeLink *next;
NodeLink *path;
};
//更新纪录八数码的状态
void setboard(int a[], int b[], int flag) //flag=0,写棋子;flag=1,写棋盘
{
for (int i = 0;i = 8;i++)
if (flag)
a[b[i]] = i;
else
b[a[i]] = i;
}
//计算启发值的函数
int calvalue(int a[]) //不在位棋子数
{
int c = 0;
for (int i = 0;i = 8;i++)
if (a[i] != goal[i])
if (goal[i] != 0)
c++;
return c;
}
//生成一个新节点的函数
NodeLink *newnode(NodeLink *TEM, int depth, int flag)
{
NodeLink *temp = new NodeLink;
for (int i = 0;i = 8;i++
文档评论(0)