A星八数码求解资料讲解.docx

上传人:b****6 文档编号:16330661 上传时间:2023-07-12 格式:DOCX 页数:14 大小:81.96KB
下载 相关 举报
A星八数码求解资料讲解.docx_第1页
第1页 / 共14页
A星八数码求解资料讲解.docx_第2页
第2页 / 共14页
A星八数码求解资料讲解.docx_第3页
第3页 / 共14页
A星八数码求解资料讲解.docx_第4页
第4页 / 共14页
A星八数码求解资料讲解.docx_第5页
第5页 / 共14页
A星八数码求解资料讲解.docx_第6页
第6页 / 共14页
A星八数码求解资料讲解.docx_第7页
第7页 / 共14页
A星八数码求解资料讲解.docx_第8页
第8页 / 共14页
A星八数码求解资料讲解.docx_第9页
第9页 / 共14页
A星八数码求解资料讲解.docx_第10页
第10页 / 共14页
A星八数码求解资料讲解.docx_第11页
第11页 / 共14页
A星八数码求解资料讲解.docx_第12页
第12页 / 共14页
A星八数码求解资料讲解.docx_第13页
第13页 / 共14页
A星八数码求解资料讲解.docx_第14页
第14页 / 共14页
亲,该文档总共14页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

A星八数码求解资料讲解.docx

《A星八数码求解资料讲解.docx》由会员分享,可在线阅读,更多相关《A星八数码求解资料讲解.docx(14页珍藏版)》请在冰点文库上搜索。

A星八数码求解资料讲解.docx

A星八数码求解资料讲解

 

A星八数码求解

实验二A*算法实验I

软工1303201326811825朱镇洋

一、实验目的:

熟悉和掌握启发式搜索的定义、估价函数和算法过程,并利用A*算法求解N数码难题,理解求解流程和搜索顺序。

二、实验原理:

A*算法是一种启发式图搜索算法,其特点在于对估价函数的定义上。

对于一般的启发式图搜索,总是选择估价函数f值最小的节点作为扩展节点。

因此,f是根据需要找到一条最小代价路径的观点来估算节点的,所以,可考虑每个节点n的估价函数值为两个分量:

从起始节点到节点n的实际代价以及从节点n到达目标节点的估价代价。

三、实验内容:

1      问题描述。

八数码问题:

在一个3×3的方阵中放入八个数码1、2、3、4、5、6、7、8,其中一个单元格是空的。

将任意摆放的数码盘(初始状态)逐步摆成某个指定的数码盘的排列(目标状态):

1

2

4

3

5

6

7

8

2

1

3

4

5

6

7

8

N个步骤

 

目标状态

起始状态

2      设计两种不同的估价函数。

w(n);w表示不在目标位置的节点数

h(n)=d(n)+;d(n)表示深度

p(n);p表示所有点到其目标节点的步数总和

 

算法流程图:

3       在求解8数码问题的A*算法程序中,设置相同的初始状态和目标状态,针对不同的估价函数,求得问题的解

令初始状态都为:

023415687目标状态为:

123405678

通过程序运行结果我们可以发现,上述两种估价函数中明显第二种在算法效率上更具优势,第一种估价函数要通过18步才能到达目标状态,通过中间变量记录扩展节点和生成节点有1062个:

而第二种估价函数只要16步即可到达目标状态,也意味着扩展节点和生成节点只有654个,比第一种少了很多:

原因分析:

通过实验结果也说明了估计函数对启发式搜索算法的重要影响,因为第二种估价函数p(n)是节点与目标节点相比所需移动次数的总和,与第一种估价函数w(n)(只考虑错误位数)相比,p(n)不仅考虑了错位信息,还考虑了错位的距离,比w(n)更完美,所以它的执行效率更高。

4启发式算法特点。

启发式搜索算法的基本思想是:

定义一个估价函数f,对当前的搜索状态进行评估,找出一个最有希望的节点来扩展。

先定义下面几个函数的含义:

f*(n)=g*(n)+h*(n)式中g*(n)表示从初始节点s到当前节点n的最短路径的耗散值;h*(n)表示从当前节点n到目标节点g的最短路径的耗散值,f*(n)表示从初始节点s经过n到目标节点g的最短路径的耗散值。

估价函数的形式可定义如下式所示:

f(n)=g(n)+h(n)其中n是被评价的当前节点。

f(n)、g(n)和h(n)分别表示是对f*(n)、g*(n)和h*(n)3个函数值的估计值。

利用估价函数f(n)=g(n)+h(n)来排列open表节点顺序的图搜索算法称为算法A。

在A算法中,如果对所有的x,

h(x)<=h*(x)成立,则称好h(x)为h*(x)的下界,它表示某种偏于保守的估计。

采用h*(x)的下界h(x)为启发函数的A算法,称为A*算法。

5扩展。

稍微改进了给定的算法,给定的算法中时在求解之后才确定是否有解,而其实判断一个八数码是否有解在输入时即可判断出该是否有解。

只要将每位上(除了空格)的特定值(此位之前比该数小的个数)相加,如果得数为偶数,那么可以确定最后有解,否则无解。

所以可以在每次输入时判断是否有解,而不必在计算完再确定是否有解,这样在算法的时间复杂度上有很大的提升,该段代码如下:

if(!

pq.empty())

{

intflag=0;

cur=pq.top();

for(inti=0;i<9;i++)

{

for(intj=0;j

{

if(cur.s[i]=='0'||cur.s[j]=='0')

continue;

else{

if(cur.s[j]

flag++;

}

}

}

if(flag%2!

=0)

return-1;//搜索失败

}

6源程序(采用上述中更高效的第二种估价函数)。

//************************************

//*八数码问题

//************************************

#include

#include

#include

#include

#include

usingnamespacestd;

structP{

intd;//深度g(n)

intw;//不在位数h(n)

intid;//记录该节点的id,用于输出时找到该节点

strings;//状态

friendbooloperator<(constP&a,constP&b){//按f(n)=g(n)+h(n)大小排序

returna.d+a.w>b.d+b.w;//最大堆

}

}p;

constintN=3;//棋盘大小

conststringt="123405678";//目标状态

stringstack[1000000];//记录搜索中的节点

stringrecord[1000000];//从起点开始记录解路径

intfather[10000000];//记录该节点的父节点

inttop=0;//stack的指针

priority_queue

pq;//open表

mapmp;//记录该状态是否已经访问过:

1访问过,0没有

intcalw(strings)//计算该状态的不在位数h(n)

{

intre=0;

for(inti=0;i<9;i++)

{

re+=abs(s[i]-t[i]);

}

returnre;

}

intsolve(int&num)//搜索过程

{

Pcur;

if(!

pq.empty())

{

intflag=0;

cur=pq.top();

for(inti=0;i<9;i++)

{

for(intj=0;j

{

if(cur.s[i]=='0'||cur.s[j]=='0')

continue;

else{

if(cur.s[j]

flag++;

}

}

}

if(flag%2!

=0)

return-1;//搜索失败

}

while(!

pq.empty()){

num++;

cur=pq.top();//open表

pq.pop();

if(cur.s==t)returncur.id;//达到目标状态,返回当前节点的id

intx,y;

intops=0;

while(cur.s[ops]!

='0')ops++;

x=ops/3,y=ops%3;//空格所在位置

intr=cur.id;

if(x>0){//空格向上移

p.s=cur.s;

swap(p.s[ops],p.s[ops-3]);

if(!

mp[p.s]){

p.d=cur.d+1,p.w=calw(p.s),p.id=top+1;

pq.push(p);

stack[++top]=p.s;

father[top]=r;

mp[p.s]=1;

}

}

if(x<2){//空格向下移

p.s=cur.s;

swap(p.s[ops],p.s[ops+3]);

if(!

mp[p.s]){

p.d=cur.d+1,p.w=calw(p.s),p.id=top+1;

pq.push(p);

stack[++top]=p.s;

father[top]=r;

mp[p.s]=1;

}

}

if(y>0){//空格向左移

p.s=cur.s;

swap(p.s[ops],p.s[ops-1]);

if(!

mp[p.s]){

p.d=cur.d+1,p.w=calw(p.s),p.id=top+1;

pq.push(p);

stack[++top]=p.s;

father[top]=r;

mp[p.s]=1;

}

}

if(y<2){//空格向右移

p.s=cur.s;

swap(p.s[ops],p.s[ops+1]);

if(!

mp[p.s]){

p.d=cur.d+1,p.w=calw(p.s),p.id=top+1;

pq.push(p);

stack[++top]=p.s;

father[top]=r;

mp[p.s]=1;

}

}

}

}

voidprint(intx)////从record表中输出当前搜索的节点

{

intk=0;

for(inti=0;i

for(intj=0;j

if(record[x][k]=='0')

printf("");

elseprintf("%c",record[x][k]);

k++;

}

printf("\n");

}

printf("\n");

}

intmain()

{

//freopen("a.txt","r",stdin);

inttt;//测试的组数

cin>>tt;

for(intk=1;k<=tt;k++){

cout<<"Case"<

\n";

inti,j;

chara;

p.s="";

for(i=0;i

for(j=0;j

cin>>a;//输入0?

8数码

p.s+=a;

}

}

p.d=0,p.w=calw(p.s),p.id=0;

father[0]=-1;

mp[p.s]=1;

stack[0]=p.s;

pq.push(p);//往open表中加入初始状态节点

intnum=0;

intid=solve(num);//调用搜索过程

if(id==-1){

cout<<"无解!

\n";

}else{

intc=-1;

while(id>=0){//把stack中存的节点按次序放入到record中

record[++c]=stack[id];

id=father[id];

}

cout<<"原图:

"<

print(c);//输出初始节点

cout<<"移动过程:

\n\n";

for(i=c-1;i>=0;i--){

cout<<"Step"<

\n";//输出当前搜索步骤

print(i);//输出当前搜索的节点

}

cout<<"移动结束!

\n";

}

mp.clear();

while(!

pq.empty())pq.pop();

top=0;

cout<

"<

cout<

}

system("pause\n");

return0;

}

第一种估价函数源代码:

intcalw(strings)//计算该状态的不在位数h(n)

{

intre=0;

for(inti=0;i<9;i++)if(s[i]!

=t[i])re++;

returnre;

}

三、实验小结:

通过此次实验,我对启发式搜索有了更深的了解,在处理该实验时,给定的两种估价函数差别不大都可以接受,但如果处理一些复杂的问题,第二种估价函数显然更为优秀,可以避免不必要的扩展。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 人文社科 > 设计艺术

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2