启发式搜索八数码问题.docx
- 文档编号:10916583
- 上传时间:2023-02-23
- 格式:DOCX
- 页数:16
- 大小:82.42KB
启发式搜索八数码问题.docx
《启发式搜索八数码问题.docx》由会员分享,可在线阅读,更多相关《启发式搜索八数码问题.docx(16页珍藏版)》请在冰豆网上搜索。
启发式搜索八数码问题
启发式搜索
1.介绍
八数码问题也称为九宫问题。
在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同.棋盘上还有一个空格(以数字0来表示),与空格相邻的棋子可以移到空格中。
要求解决的问题是:
给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤.
所谓问题的一个状态就是棋子在棋盘上的一种摆法。
解八数码问题实际上就是找出从初始状态到达目标状态所经过的一系列中间过渡状态。
2.使用启发式搜索算法求解8数码问题。
1)A ,A星算法采用估价函数
其中:
是搜索树中结点
的深度;
为结点
的数据库中错放的棋子个数;
为结点
的数据库中每个棋子与其目标位置之间的距离总和。
2)宽度搜索采用f(i)为i的深度,深度搜索采用f(i)为i的深度的倒数。
3.算法流程
1把起始节点S放到OPEN表中,并计算节点S的
;
2如果OPEN是空表,则失败退出,无解;
3从OPEN表中选择一个
值最小的节点
.如果有几个节点值相同,当其中有一个
为目标节点时,则选择此目标节点;否则就选择其中任一个节点作为节点
;
4把节点
从OPEN 表中移出,并把它放入CLOSED的已扩展节点表中;
5如果
是个目标节点,则成功退出,求得一个解;
6扩展节点
,生成其全部后继节点。
对于
的每一个后继节点
:
计算
;如果
既不在OPEN表中,又不在CLOCED表中,则用估价函数
把
它添入OPEN表中.从
加一指向其父节点
的指针,以便一旦找到目标节点时记住一个解答路径;如果
已在OPEN表或CLOSED表中,则比较刚刚对
计算过的
和前面计算过的该节点在表中的
值。
如果新的
较小,则
(I)以此新值取代旧值.
(II)从
指向
而不是指向他的父节点.
(III)如果节点
在CLOSED表中,则把它移回OPEN表中。
7转向②,即GOTO②。
4.估价函数
计算一个节点的估价函数,可以分成两个部分:
1、已经付出的代价(起始节点到当前节点);
2、将要付出的代价(当前节点到目标节点)。
节点n的估价函数
定义为从初始节点、经过n、到达目标节点的路径的最小代价的估计值,即
=
+
。
是从初始节点到达当前节点n的实际代价;
是从节点n到目标节点的最佳路径的估计代价,体现出搜索过程中采用的启发式信息(背景知识),称之为启发函数.
所占的比重越大,越趋向于宽度优先或等代价搜索;反之,
的比重越大,表示启发性能就越强。
5.实验代码
为方便起见,目标棋局为不变
(1)以下代码估价函数为深度+错放棋子个数
(2) 若估价函数为深度+每个棋子与其目标位置之间的距离总和,则加入估价函数
intcalvalue1(inta[]) //不在位棋子数
{
intc=0;
int b=0;
ﻩfor(inti=0;i〈=8;i++)
for (intj= 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);
ﻩreturnc;
}
(3)宽度搜索采用OPEN-〉jiedian.f= depth;
(4)深度搜索采用OPEN-〉jiedian.f= -depth;
源代码:
1.#include"stdio。
h"
2.intgoal[9]={1,2,3,8,0,4,7,6,5},sgoal[9];//goal为棋盘的目标布局,并用中间状态sgoal与之比较
3.structBoard
4.{
5.ﻩintshuzu[9];
6.intd,f, e;//d:
深度;f:
启发函数;e:
记录前一次的扩展节点
7.};
8.structNodeLink
9.{
10.Boardjiedian;
11.NodeLink*parent;
12.NodeLink *previous;
13.NodeLink*next;
14.NodeLink*path;
15.};
16.//更新纪录八数码的状态
17.voidsetboard(int a[],intb[],int flag) //flag=0,写棋子;flag=1,写棋盘
18.{
19.for(inti= 0;i<= 8;i++)
20.ﻩif(flag)
21.ﻩﻩa[b[i]]= i;
22.ﻩelse
23.b[a[i]]=i;
24.}
25.//计算启发值的函数
26.int calvalue(int a[]) //不在位棋子数
27.{
28.intc=0;
29.ﻩfor(inti= 0;i〈= 8;i++)
30.ﻩﻩif(a[i]!
= goal[i])
31.ﻩif(goal[i]!
=0)
32.ﻩﻩﻩc++;
33.return c;
34.}
35.//生成一个新节点的函数
36.NodeLink*newnode(NodeLink*TEM, intdepth, intflag)
37.{
38.NodeLink*temp =new NodeLink;
39.for (inti = 0;i<=8;i++)
40.ﻩtemp->jiedian。
shuzu[i] =TEM->jiedian.shuzu[i];
41.ﻩswitch(flag)
42.{
43.case1:
44.{
45.ﻩﻩtemp—〉jiedian。
shuzu[0]——;
46.temp->jiedian.shuzu[sgoal[temp-〉jiedian.shuzu[0]]]++; //向左移
47.break;
48.}
49.ﻩcase2:
50.ﻩ{
51.temp—>jiedian.shuzu[0]++;
52.ﻩﻩtemp-〉jiedian。
shuzu[sgoal[temp—〉jiedian.shuzu[0]]]—-;//向右移
53.break;
54.ﻩ}
55.ﻩcase3:
56.ﻩ{
57.ﻩﻩtemp—>jiedian.shuzu[0]-=3;
58.ﻩtemp—>jiedian.shuzu[sgoal[temp->jiedian.shuzu[0]]]+=3;//向上移
59.break;
60.ﻩ}
61.case4:
62.ﻩ{
63.ﻩﻩtemp—〉jiedian。
shuzu[0]+=3;
64.ﻩtemp->jiedian。
shuzu[sgoal[temp—>jiedian.shuzu[0]]]—=3; //向下移
65.ﻩﻩbreak;
66.ﻩ}
67.}
68.ﻩtemp->jiedian.d=depth+1;
69.setboard(sgoal,temp-〉jiedian.shuzu,1);
70.temp—〉jiedian。
f= temp->jiedian。
d+calvalue(sgoal);
71.temp->jiedian。
e= flag;
72.temp->parent =TEM;
73.ﻩreturntemp;
74.}
75.//把新节点加入OPEN队列
76.NodeLink *addnode(NodeLink*head,NodeLink*node) //把node插入到head链中
77.{
78.ﻩNodeLink*TEM;
79.TEM= head;
80.head=node;
81.ﻩhead->next=TEM;
82.ﻩhead-〉previous=NULL;
83.ﻩif(TEM)
84.ﻩﻩTEM—〉previous =head; //TEM已为空,无需操作
85.ﻩreturnhead;
86.}
87.//求启发值最小的结点
88.NodeLink*minf(NodeLink*head)
89.{
90.ﻩNodeLink *min,*forward;
91.ﻩmin=head;
92.forward=head;
93.ﻩwhile(forward)
94.{
95.ﻩif(min—>jiedian.f>forward—〉jiedian.f)
96.min= forward;
97.ﻩforward=forward->next;
98.ﻩ}
99.ﻩreturnmin;
100.}
101.intmain()
102.{
103.ﻩintdepth=0;
104.int source[9];
105.int i, j;
106.NodeLink*OPEN=newNodeLink;
107.NodeLink*TEMP,*TEM;
108.ﻩprintf(”请输入初始状态:
\n");
109.ﻩfor(i=0;i〈9;i++)
110.ﻩﻩscanf_s("%d”,&source[i]);
111.ﻩsetboard(source,OPEN-〉jiedian.shuzu,0);
112.OPEN->jiedian.d =depth;
113.ﻩOPEN-〉jiedian.e= 0;
114.OPEN->jiedian。
f=depth +calvalue(source);
115.OPEN—>next= NULL;
116.ﻩOPEN->previous= NULL;
117.OPEN—>parent =NULL;
118.while(OPEN)
119.{
120.TEMP=minf(OPEN); //求具有最小启发值的节点
121.setboard(sgoal,TEMP—>jiedian。
shuzu, 1); //写棋盘
122.ﻩif(!
calvalue(sgoal))
123.ﻩﻩﻩbreak;
124.ﻩif(TEMP !
= OPEN) //如果不是第一个节点
125.ﻩﻩ{
126.ﻩﻩTEMP-〉previous->next=TEMP-〉next;
127.ﻩTEMP—>next->previous= TEMP->previous;
128.ﻩ}
129.else //是第一个节点
130.ﻩﻩ{
131.ﻩﻩif (OPEN->next) //如果还有节点
132.{
133.ﻩﻩﻩOPEN= OPEN-〉next;
134.ﻩﻩOPEN->previous=NULL;
135.ﻩﻩ}
136.ﻩﻩelse OPEN=NULL; //否则置为空
137.}
138.ﻩﻩif(TEMP-〉jiedian。
shuzu[0]— 1 >=0&&TEMP->jiedian.e!
=2) //防止棋子回到原状态
139.ﻩOPEN = addnode(OPEN,newnode(TEMP,depth, 1));
140.ﻩﻩif (TEMP—>jiedian.shuzu[0]+1<=8&&TEMP—>jiedian。
e!
= 1)
141.ﻩﻩOPEN= addnode(OPEN,newnode(TEMP, depth,2));
142.ﻩif (TEMP—〉jiedian。
shuzu[0]—3>= 0&&TEMP-〉jiedian.e !
= 4)
143.ﻩﻩﻩOPEN= addnode(OPEN, newnode(TEMP,depth,3));
144.ﻩif (TEMP—〉jiedian.shuzu[0]+ 3 <=8&&TEMP->jiedian.e!
=3)
145.ﻩOPEN= addnode(OPEN,newnode(TEMP,depth, 4));
146.depth++;
147.}
148.ﻩif(OPEN) //如有解,则打印出解的步骤
149.ﻩ{
150.TEMP-〉path = NULL;
151.ﻩwhile (TEMP—〉parent) //每次回溯父节点,生成路径
152.ﻩ{
153.ﻩﻩTEMP-〉parent-〉path=TEMP;
154.ﻩﻩﻩTEMP = TEMP->parent;
155.}
156.ﻩj=0;
157.ﻩwhile(TEMP->path)
158.ﻩ{
159.ﻩsetboard(sgoal, TEMP-〉jiedian。
shuzu,1);
160.ﻩprintf("第%d步:
\n",j);
161.ﻩﻩﻩfor(i=0;i<=2;i++)
162.ﻩprintf("%d”,sgoal[i]);
163.ﻩﻩprintf("\n");
164.ﻩﻩfor(i=3;i <=5;i++)
165.ﻩﻩﻩprintf(" %d”, sgoal[i]);
166.ﻩprintf("\n”);
167.ﻩfor (i=6;i<=8;i++)
168.ﻩﻩﻩprintf(”%d”,sgoal[i]);
169.ﻩﻩprintf("\n");
170.ﻩﻩTEMP=TEMP-〉path;
171.j++;
172.}
173.ﻩﻩsetboard(sgoal,TEMP—>jiedian.shuzu,1);
174.ﻩprintf("第%d步:
\n”,j);
175.for(i= 0;i<=2;i++)
176.ﻩprintf("%d”,sgoal[i]);
177.ﻩprintf(”\n");
178.ﻩfor(i =3;i〈=5;i++)
179.ﻩprintf("%d",sgoal[i]);
180.ﻩprintf("\n");
181.ﻩﻩfor(i=6;i<=8;i++)
182.ﻩprintf(” %d",sgoal[i]);
183.printf(”\n”);
184.ﻩ}
185.else
186.ﻩprintf("无法求解!
");
187.}
(1)以上代码估价函数为深度+错放棋子个数
(2)若估价函数为深度+每个棋子与其目标位置之间的距离总和,则函数改为
int calvalue(inta[])//不在位棋子数
{
ﻩint c=0;
int b=0;
for(inti=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;
6.输出结果:
(输入为:
)
目标状态为:
(1)估价函数为深度+错放棋子个数
(2)估价函数为深度+每个3棋子与其目标位置之间的距离总和
(3)宽度搜索采用OPEN->jiedian。
f =depth;
(4) 深度搜索采用OPEN-〉jiedian。
f =-depth;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 启发式 搜索 数码 问题