启发式搜索八数码问题Word文档格式.docx
《启发式搜索八数码问题Word文档格式.docx》由会员分享,可在线阅读,更多相关《启发式搜索八数码问题Word文档格式.docx(14页珍藏版)》请在冰豆网上搜索。
对于
的每一个后继节点
:
计算
如果
既不在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;
intb=0;
for(inti=0;
i<
=8;
i++)
for(intj=0;
j<
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->
=depth;
(4)深度搜索采用OPEN->
=-depth;
源代码:
1.#include"
"
2.
3.intgoal[9]={1,2,3,8,0,4,7,6,5},sgoal[9];
//goal为棋盘的目标布局,并用中间状态sgoal与之比较
4.
5.structBoard
6.{
7.intshuzu[9];
8.intd,f,e;
//d:
深度;
f:
启发函数;
e:
记录前一次的扩展节点
9.};
10.
11.structNodeLink
12.{
13.Boardjiedian;
14.NodeLink*parent;
15.NodeLink*previous;
16.NodeLink*next;
17.NodeLink*path;
18.};
19.//更新纪录八数码的状态
20.voidsetboard(inta[],intb[],intflag)//flag=0,写棋子;
flag=1,写棋盘
21.{
22.for(inti=0;
23.if(flag)
24.a[b[i]]=i;
25.else
26.b[a[i]]=i;
27.}
28.//计算启发值的函数
29.intcalvalue(inta[])//不在位棋子数
30.{
31.intc=0;
32.for(inti=0;
33.if(a[i]!
=goal[i])
34.if(goal[i]!
35.c++;
36.returnc;
37.}
38.//生成一个新节点的函数
39.NodeLink*newnode(NodeLink*TEM,intdepth,intflag)
40.{
41.NodeLink*temp=newNodeLink;
42.for(inti=0;
43.temp->
[i]=TEM->
[i];
44.switch(flag)
45.{
46.case1:
47.{
48.temp->
[0]--;
49.temp->
[sgoal[temp->
[0]]]++;
//向左移
50.break;
51.}
52.case2:
53.{
54.temp->
[0]++;
55.temp->
[0]]]--;
//向右移
56.break;
57.}
58.case3:
59.{
60.temp->
[0]-=3;
61.temp->
[0]]]+=3;
//向上移
62.break;
63.}
64.case4:
65.{
66.temp->
[0]+=3;
67.temp->
[0]]]-=3;
//向下移
68.break;
69.}
70.}
71.temp->
=depth+1;
72.setboard(sgoal,temp->
1);
73.temp->
=temp->
+calvalue(sgoal);
74.temp->
=flag;
75.temp->
parent=TEM;
76.returntemp;
77.}
78.//把新节点加入OPEN队列
79.NodeLink*addnode(NodeLink*head,NodeLink*node)//把node插入到head链中
80.{
81.NodeLink*TEM;
82.TEM=head;
83.head=node;
84.head->
next=TEM;
85.head->
previous=NULL;
86.if(TEM)
87.TEM->
previous=head;
//TEM已为空,无需操作
88.returnhead;
89.}
90.
91.//求启发值最小的结点
92.NodeLink*minf(NodeLink*head)
93.{
94.NodeLink*min,*forward;
95.min=head;
96.forward=head;
97.while(forward)
98.{
99.if(min->
>
forward->
100.min=forward;
101.forward=forward->
next;
102.}
103.returnmin;
104.}
105.
106.intmain()
107.{
108.intdepth=0;
109.intsource[9];
110.inti,j;
111.
112.NodeLink*OPEN=newNodeLink;
113.NodeLink*TEMP,*TEM;
114.
115.printf("
请输入初始状态:
\n"
);
116.for(i=0;
i<
9;
117.scanf_s("
%d"
&
source[i]);
118.
119.setboard(source,OPEN->
0);
120.OPEN->
121.OPEN->
=0;
122.OPEN->
=depth+calvalue(source);
123.OPEN->
next=NULL;
124.OPEN->
125.OPEN->
parent=NULL;
126.
127.while(OPEN)
128.{
129.TEMP=minf(OPEN);
//求具有最小启发值的节点
130.setboard(sgoal,TEMP->
//写棋盘
131.if(!
calvalue(sgoal))
132.break;
133.if(TEMP!
=OPEN)//如果不是第一个节点
134.{
135.TEMP->
previous->
next=TEMP->
136.TEMP->
next->
previous=TEMP->
previous;
137.}
138.else//是第一个节点
139.{
140.if(OPEN->
next)//如果还有节点
141.{
142.OPEN=OPEN->
143.OPEN->
144.}
145.elseOPEN=NULL;
//否则置为空
146.}
147.
148.if(TEMP->
[0]-1>
=0&
&
TEMP->
!
=2)//防止棋子回到原状态
149.OPEN=addnode(OPEN,newnode(TEMP,depth,1));
150.if(TEMP->
[0]+1<
=8&
=1)
151.OPEN=addnode(OPEN,newnode(TEMP,depth,2));
152.if(TEMP->
[0]-3>
=4)
153.OPEN=addnode(OPEN,newnode(TEMP,depth,3));
154.if(TEMP->
[0]+3<
=3)
155.OPEN=addnode(OPEN,newnode(TEMP,depth,4));
156.depth++;
157.}
158.
159.if(OPEN)//如有解,则打印出解的步骤
160.{
161.TEMP->
path=NULL;
162.while(TEMP->
parent)//每次回溯父节点,生成路径
163.{
164.TEMP->
parent->
path=TEMP;
165.TEMP=TEMP->
parent;
166.}
167.j=0;
168.while(TEMP->
path)
169.{
170.setboard(sgoal,TEMP->
171.printf("
第%d步:
j);
172.for(i=0;
=2;
173.printf("
%d"
sgoal[i]);
174.printf("
\n"
175.for(i=3;
=5;
176.printf("
177.printf("
178.for(i=6;
179.printf("
180.printf("
181.TEMP=TEMP->
path;
182.j++;
183.}
184.setboard(sgoal,TEMP->
185.printf("
186.for(i=0;
187.printf("
188.printf("
189.for(i=3;
190.printf("
191.printf("
192.for(i=6;
193.printf("
194.printf("
195.}
196.else
197.printf("
无法求解!
198.}
(1)以上代码估价函数为深度+错放棋子个数
(2)若估价函数为深度+每个棋子与其目标位置之间的距离总和,则函数改为
intcalvalue(inta[])//不在位棋子数
6.输出结果:
(输入为:
)
目标状态为:
(1)估价函数为深度+错放棋子个数
(2)估价函数为深度+每个3棋子与其目标位置之间的距离总和