八数码问题求解--实验报告讲解

合集下载

八数码问题 实验报告

八数码问题 实验报告

八数码问题实验报告八数码问题实验报告引言:八数码问题是一种经典的数学难题,在计算机科学领域有着广泛的研究和应用。

本实验旨在通过探索八数码问题的解法,深入理解该问题的本质,并通过实验结果评估不同算法的效率和准确性。

一、问题描述:八数码问题是一个在3×3的棋盘上,由1至8的数字和一个空格组成的拼图问题。

目标是通过移动棋盘上的数字,使得棋盘上的数字排列按照从小到大的顺序排列,最终形成如下的目标状态:1 2 34 5 67 8二、解法探索:1. 深度优先搜索算法:深度优先搜索算法是一种经典的解决拼图问题的方法。

该算法通过不断尝试所有可能的移动方式,直到找到目标状态或者无法再继续移动为止。

实验结果显示,该算法在八数码问题中能够找到解,但由于搜索空间庞大,算法的时间复杂度较高。

2. 广度优先搜索算法:广度优先搜索算法是另一种常用的解决八数码问题的方法。

该算法通过逐层扩展搜索树,从初始状态开始,逐步扩展所有可能的状态,直到找到目标状态。

实验结果显示,该算法能够找到最短路径的解,但同样面临搜索空间庞大的问题。

3. A*算法:A*算法是一种启发式搜索算法,结合了深度优先搜索和广度优先搜索的优点。

该算法通过使用一个估价函数来评估每个搜索状态的优劣,并选择最有希望的状态进行扩展。

实验结果显示,A*算法在八数码问题中表现出色,能够高效地找到最优解。

三、实验结果与分析:通过对深度优先搜索、广度优先搜索和A*算法的实验,得出以下结论:1. 深度优先搜索算法虽然能够找到解,但由于搜索空间庞大,时间复杂度较高,不适用于大规模的八数码问题。

2. 广度优先搜索算法能够找到最短路径的解,但同样面临搜索空间庞大的问题,对于大规模问题效率较低。

3. A*算法在八数码问题中表现出色,通过合理的估价函数能够高效地找到最优解,对于大规模问题具有较好的效果。

四、结论与展望:本实验通过对八数码问题的解法探索,深入理解了该问题的本质,并评估了不同算法的效率和准确性。

人工智能导论:状态空间搜索实验—八数码问题求解解读

人工智能导论:状态空间搜索实验—八数码问题求解解读

昆明理工大学信息工程与自动化学院学生实验报告( 2014—— 2015 学年 第 一 学期 )课程名称:人工智能导论 开课实验室: 年 月 日一、实验内容和要求八数码问题:在3×3的方格棋盘上,摆放着1到8这八个数码,有1个方格是空的,其初始状态如图1所示,要求对空格执行空格左移、空格右移、空格上移和空格下移这四个操作使得棋盘从初始状态到目标状态。

例如:(a) 初始状态 (b) 目标状态图1 八数码问题示意图请任选一种盲目搜索算法(广度优先搜索或深度优先搜索)或任选一种启发式搜索方法(全局择优搜索,加权状态图搜索,A 算法或 A * 算法)编程求解八数码问题(初始状态任选)。

选择一个初始状态,画出搜索树,填写相应的OPEN 表和CLOSED 表,给出解路径,对实验结果进行分析总结,得出结论。

实验报告内容格式要求:XXXXXXXXXXXX (中文:宋体,小四;英文:Times New Roman )。

二、实验目的1. 熟悉人工智能系统中的问题求解过程;2. 熟悉状态空间的盲目搜索和启发式搜索算法的应用;3. 熟悉对八数码问题的建模、求解及编程语言的应用。

三、实验算法启发函数设定由八数码问题的部分状态图可以看出,从初始节点开始,在通向目标节点的路径上,各节点的数码格局同目标节点相比较,其数码不同的位置个数在逐渐减少,最后为零,因此可以把数码不同的位置个数作为标志一个节点到目标节点距离远近的一个启发性信息,利用这个信息来扩展节点的选择,减少搜索范围,提高搜索速度。

2、数据结构与算法设计数码结构体typedef struct node //八数码结构体{int form[N][N]; //数码组int evalue; //评估值,差距int udirec; //所屏蔽方向,防止往回推到上一状态,1上2下3左4右struct node *parent; //父节点}Graph;Graph *Qu[MAX];//队列Graph *St[MAX];//堆栈搜索过程:(搜索采用广度搜索方式,利用待处理队列辅助,逐层搜索(跳过劣质节点))a、把初始数码组压入队列;b、从队列中取出一个数码组节点;c、扩展子节点,即从上下左右四个方向移动空格,生成相应子节点:d、对子节点数码组作评估,是否为优越节点,即其评估值是否小于等于其父节点加一,是则将其压入队,否则抛弃。

八数码实验报告

八数码实验报告

八数码实验报告八数码实验报告引言:八数码,也被称为滑块拼图,是一种经典的益智游戏。

在这个实验中,我们将探索八数码问题的解决方案,并分析其算法的效率和复杂性。

通过这个实验,我们可以深入了解搜索算法在解决问题中的应用,并且探讨不同算法之间的优劣势。

1. 问题描述:八数码问题是一个在3x3的方格上进行的拼图游戏。

方格中有8个方块,分别标有1到8的数字,还有一个空方块。

游戏的目标是通过移动方块,将它们按照从左上角到右下角的顺序排列。

2. 算法一:深度优先搜索(DFS)深度优先搜索是一种经典的搜索算法,它从初始状态开始,不断地向前搜索,直到找到目标状态或者无法继续搜索为止。

在八数码问题中,深度优先搜索会尝试所有可能的移动方式,直到找到解决方案。

然而,深度优先搜索在解决八数码问题时存在一些问题。

由于搜索的深度可能非常大,算法可能会陷入无限循环,或者需要很长时间才能找到解决方案。

因此,在实际应用中,深度优先搜索并不是最优的选择。

3. 算法二:广度优先搜索(BFS)广度优先搜索是另一种常用的搜索算法,它从初始状态开始,逐层地向前搜索,直到找到目标状态。

在八数码问题中,广度优先搜索会先尝试所有可能的一步移动,然后再尝试两步移动,依此类推,直到找到解决方案。

与深度优先搜索相比,广度优先搜索可以保证找到最短路径的解决方案。

然而,广度优先搜索的时间复杂度较高,尤其是在搜索空间较大时。

因此,在实际应用中,广度优先搜索可能不太适合解决八数码问题。

4. 算法三:A*算法A*算法是一种启发式搜索算法,它在搜索过程中利用了问题的启发信息,以提高搜索效率。

在八数码问题中,A*算法会根据每个状态与目标状态之间的差异,选择最有可能的移动方式。

A*算法通过综合考虑每个状态的实际代价和启发式估计值,来评估搜索路径的优劣。

通过选择最优的路径,A*算法可以在较短的时间内找到解决方案。

然而,A*算法的实现较为复杂,需要合适的启发函数和数据结构。

八数码实验报告

八数码实验报告

八数码实验报告实验名称:八数码实验目的:通过使用搜索算法和启发式算法,解决八数码问题,深入理解搜索算法原理和应用。

实验环境:使用Python语言进行编程实现,操作系统为Windows。

实验过程:1. 定义八数码问题的状态和目标状态,分别以列表的形式表示。

* 初始状态:[2, 8, 3, 1, 6, 4, 7, 0, 5]* 目标状态:[1, 2, 3, 8, 0, 4, 7, 6, 5]2. 实现深度优先搜索算法,运行程序得到结果。

通过深度优先搜索算法,得到了八数码问题的解法。

但是,由于深度优先搜索算法过于盲目,搜索时间过长,而且容易陷入无解状态,因此需要改进算法。

3. 改进算法——广度优先搜索。

在深度优先搜索的基础上,改用广度优先搜索算法,实现代码如下:```def bfs(start, target):queue = [(start, [start])]seen = {tuple(start)}while queue:node, path = queue.pop(0)for move, i in direction.items():new_node = [j for j in node]if i not in range(0, 9):continuenew_node[0], new_node[i] = new_node[i], new_node[0] if tuple(new_node) in seen:continueif new_node == target:return path + [new_node]seen.add(tuple(new_node))queue.append((new_node, path + [new_node]))```4. 改进算法——A*算法。

在广度优先搜索的基础上,使用A*算法进行优化。

进行了以下改进:* 引入估价函数,加快搜索速度;* 遍历过程中对结点进行评估,保留最优的结点。

八个数字问题实验报告.doc

八个数字问题实验报告.doc

八个数字问题实验报告. 《八数码问题》实验报告首先,实验的目的:熟悉启发式搜索算法。

二、实验内容:启发式搜索算法用于解决8位数问题。

编制了程序,实现了解决8位数问题的算法。

采用评估功能,其中:是搜索树中节点的深度;在节点数据库中放错位置的件数;这是每个棋子与其在节点数据库中的目标位置之间距离的总和。

三、实验原理:1.问题描述:八位数问题也被称为九宫问题。

在3×3的棋盘上,有八个棋子,每一个棋子都标有一定的1到8的数字,不同棋子上标的数字是不同的。

棋盘上还有一个空格(用数字0表示),与空格相邻的棋子可以移动到空格中。

要解决的问题是: 给定初始状态和目标状态,找出从初始状态到目标状态移动次数最少的移动步骤。

所谓问题的一种状态是棋盘上棋子的排列。

解决八位数问题实际上是找出一系列从初始状态到目标状态的中间过渡状态。

2.原则描述:启发式搜索(1)原理启发式搜索是评估每个搜索在状态空间中的位置以获得最佳位置,然后从这个位置搜索到目标。

这样,可以省略大量不必要的搜索路径,并且提高了效率。

在启发式搜索中,位置的评估非常重要。

不同的评估会产生不同的效果。

(2)评估函数计算节点的评估函数,可分为两部分:1.成本已经支付(从开始节点到当前节点);2.要支付的价格(当前节点到目标节点)。

节点n的评估函数被定义为从初始节点通过n到目标节点的路径的最小成本的估计值,即=。

是从初始节点到达当前节点n的实际成本;是从节点n到目标节点的最佳路径的估计开销。

比例越大,它越倾向于先搜索宽度或同等成本。

相反,比例越大,启发式性能越强。

(3)算法描述:(1)将起始节点S放入OPEN表中,计算节点S的值;(2)如果OPEN为空表,则无法退出且没有解决方案;(3)从OPEN表中选择具有最小值的节点。

如果多个节点具有相同的值,当其中一个节点是目标节点时,选择目标节点;否则,任意一个节点被选为节点;(4)从OPEN表中移除节点,并将其放入CLOSED扩展节点表中;(5)如果它是目标节点,它成功退出并获得解决方案;⑥扩展节点以生成其所有后续节点。

八数码问题求解--实验报告讲解-共16页

八数码问题求解--实验报告讲解-共16页

实验报告一、实验问题八数码问题求解二、实验软件VC6.0 编程语言或其它编程语言三、实验目的1. 熟悉人工智能系统中的问题求解过程;2. 熟悉状态空间的盲目搜索和启发式搜索算法的应用;3. 熟悉对八数码问题的建模、求解及编程语言的应用。

四、实验数据及步骤(一、)实验内容八数码问题:在3×3的方格棋盘上,摆放着1到8这八个数码,有1个方格是空的,其初始状态如图1所示,要求对空格执行空格左移、空格右移、空格上移和空格下移这四个操作使得棋盘从初始状态到目标状态。

2 83 1 2 31 4 8 47 6 5 7 6 5(a) 初始状态(b) 目标状态图1 八数码问题示意图(二、)基本数据结构分析和实现1.结点状态我采用了struct Node数据类型typedef struct _Node{int digit[ROW][COL];int dist; // distance between one state and the destination一个表和目的表的距离int dep; // the depth of node深度// So the comment function = dist + dep.估价函数值int index; // point to the location of parent父节点的位置} Node; 2.发生器函数定义的发生器函数由以下的四种操作组成:(1)将当前状态的空格上移Node node_up;Assign(node_up, index);//向上扩展的节点int dist_up = MAXDISTANCE;(2)将当前状态的空格下移Node node_down;Assign(node_down, index);//向下扩展的节点int dist_down = MAXDISTANCE;(3)将当前状态的空格左移Node node_left;Assign(node_left, index);//向左扩展的节点int dist_left = MAXDISTANCE;(4)将当前状态的空格右移Node node_right;Assign(node_right, index);//向右扩展的节点int dist_right = MAXDISTANCE;通过定义结点状态和发生器函数,就解决了8数码问题的隐式图的生成问题。

八数码难题

八数码难题

八数码难题一、问题简介八方块移动游戏要求从一个含8个数字(用1-8表示)的方块以及一个空格方块(用0表示)的3x3矩阵的起始状态开始,不断移动该空格方块以使其和相邻的方块互换,直至达到所定义的目标状态。

空格方块在中间位置时有上、下、左、右4个方向可移动,在四个角落上有2个方向可移动,在其他位置上有3个方向可移动。

例如,假设一个3x3矩阵的初始状态为:8 0 32 1 47 6 5目标状态为:1 2 38 0 47 6 5二、算法分析1、问题表示:问题表示的核心是如何存储搜索过程中得到的状态。

本人是这样存储的:对每个状态用一个9位数存储,例如:把初始状态:8 0 32 1 47 6 5存储为一个9位数:8032147652、问题分析想法一:采用插入排序的方法,八数码问题好比是一列数,将各个行列的数字按大小排列,在插入的时候考虑方向性和比较性,对每个数字节点设置前后左右四个属性,分别在初始状态比较各自队列的大小,比如按照左前右后顺时针的方向依次比较和移动,设置哨兵,循环比较,最后得到的序列也就是八数码问题迎刃而解了。

想法二:采用prolog语言表示,Prolog(Programming in Logic的缩写)是一种逻辑编程语言。

它建立在逻辑学的理论基础之上,最初被运用于自然语言等研究领域。

现在它已广泛的应用在人工智能的研究中,它可以用来建造专家系统、自然语言理解、智能知识库等。

2、解题算法:广度搜索常用的优化方法:哈希表法——记录队列中已有节点,用于判断是否需要扩展节点。

A*算法——构造估价函数。

双向广度优先搜索——从源节点、目标节点一起开始搜索。

三、算法实现本程序用了广度优先搜索这种策略进行搜索,且其搜索深度限制在1000内,其代码实现如下:#include "stack1.h"#include<time.h>stack open,closed;//表的基本操作void swap(int &a,int &b)//比较数字{int bak=a; a=b; b=bak;}int isok(int pos)//界限判断{return pos>=0&&pos<3*3;}int isdiff(int ch[])//判断输入数码是否合法{for(int i=0;i<3*3-1;i++)for(int j=i+1;j<3*3;j++)if(ch[i]==ch[j]||!isok(i)||!isok(j))return 0;return 1;}void init(int ch[],int flag)//初始化数码,键盘输入{cout<<"请输入目标状态:("<<3*3<<"个)"<<endl;for( int j=0;j<3*3;j++)cin>>chdes[j];while(!(isdiff(chdes))){cout<<"初始化错误,数据不合理!"<<endl;cout<<"请输入目标状态:("<<3*3<<"个)"<<endl;for( j=0;j<3*3;j++)cin>>chdes[j];}cout<<"请输入初始状态:("<<3*3<<"个)"<<endl;for(j=0;j<3*3;j++)cin>>ch[j];while(!(isdiff(ch))){cout<<"初始化错误,数据不合理!"<<endl;cout<<"请输入初始状态:("<<3*3<<"个)"<<endl;for(j=0;j<3*3;j++)cin>>ch[j];}for(j=0;j<3*3;j++)chbak[j]=ch[j];}int findnext(int pos,int step)//找到移动位置{if(step>=0&&step<4) //四个方向移动{switch(step){case 0:if(isok(pos-3))return pos-3;return -1;break;case 1:if(isok(pos+1)&&pos/3==(pos+1)/3)return pos+1;return -1;break;case 2:if(isok(pos+3))return pos+3;return -1;break;case 3:if(isok(pos-1)&&pos/3==(pos-1)/3)return pos-1;return -1;break;}}return -1;}int getnum(int pos){if(isok(pos)){for(int i=0;i<3*3;i++)if(chdes[i]==ch[pos])return(abs(i/3-pos/3)+abs(i%3-pos%3));}return 0;}int getallnum(){int sum=0;for(int i=0;i<3*3;i++)sum+=getnum(i);return sum;}int findzero(int ch[]){for(int i=0;i<3*3;i++)if(ch[i]==0)return i;return -1;}void showparent(node *root)//递归方式显示结果路径{if(root->pre!=-1){showparent(&arr[root->pre]);root->show();cout<<"--第"<<root->precost+1<<"步--"<<endl;}}void showchar(int ch[])//显示一个状态{for(int i=0;i<3*3;i++){cout<<ch[i]<<" ";if((i+1)%3==0)cout<<endl;}}int getpath(node *thisnode,int &sums)//递归方式搜索最优路径{if(sums>=9*maxsize/10){cout<<"应该是没有解路径,需要太多空间!(需存储"<<jiecheng(3*3)<<" 个状态!)"<<endl;return 0;}else{for(int i=0;i<3*3;i++)ch[i]=thisnode->ch1[i];for(i=0;i<4;i++)//从四个方位搜索{int pos1=findnext(thisnode->pos,i);//搜索的位置if(pos1!=-1)//搜索的位置合法{swap(ch[pos1],ch[thisnode->pos]);//移动数码int hn=getallnum();if(hn==0){cout<<"a solution is :"<<endl;showchar(chbak);cout<<"--第1步--"<<endl;showparent(thisnode);showchar(chdes);return 1;}elseif(hn>0)//如果没有到达目标状态{arr[sums].nextcost=hn;arr[sums].precost=thisnode->precost+1;//已经走过的路程arr[sums].pos=findzero(ch);//空格的位置for(int j=0;j<3*3;j++)//当前的状态arr[sums].ch1[j]=ch[j];arr[sums].pre=thisnode->id;if(!(open.cmp(&arr[sums])||closed.cmp(&arr[sums]))){open.insert(&arr[sums]);sums++;}}swap(ch[pos1],ch[thisnode->pos]);}}if(!open.isempty()){node *tem=open.del();closed.insert1(tem);getpath(tem,sums);}else{cout<<"没有解路径!"<<endl;return 0;}}return 0;}void main(){char cls[4]="cls",input='1';int flag=1,sum=1;while(input>='1'&&input<='4'){open.clear();closed.clear();sum=1;flag=1;select();cin>>input;if(input>='1'&&input<='4'){switch(input){case '1':init(ch,0);break;case '2':system(cls);flag=2;}if(flag==1){for(int i=0;i<maxsize;i++)arr[i].id=i;arr[0].precost=0;arr[0].pre=-1;arr[0].pos=findzero(ch);arr[0].nextcost=getallnum();for(i=0;i<3*3;i++)arr[0].ch1[i]=ch[i];open.insert(&arr[0]);node *p=open.del();closed.insert1(p);cout<<"目标状态:"<<endl;showchar(chdes);cout<<"初始状态:"<<endl;showchar(chbak);if(arr[0].nextcost>0)getpath(&arr[0],sum);elsecout<<"初始状态为目标状态!"<<endl;}}}}四、实验分析实验界面为:本实验采取表的排序,并利用广度优先搜索来查找路径,基本实现了实验要求,仍有不完善之处,仍需继续改正。

人工智能实验一_八数码问题

人工智能实验一_八数码问题

用A*算法解决八数码问题1 问题描述1.1 待解决问题的解释八数码游戏(八数码问题)描述为:在3×3组成的九宫格棋盘上,摆有八个将牌,每一个将牌都刻有1-8八个数码中的某一个数码。

棋盘中留有一个空格,允许其周围的某一个将牌向空格移动,这样通过移动将牌就可以不断改变将牌的布局。

这种游戏求解的问题是:给定一种初始的将牌布局或结构(称初始状态)和一个目标的布局(称目标状态),问如何移动将牌,实现从初始状态到目标状态的转变。

1.2 问题的搜索形式描述(4要素)初始状态:8个数字将牌和空格在九宫格棋盘上的所有格局组成了问题的状态空间。

其中,状态空间中的任一种状态都可以作为初始状态。

后继函数:通过移动空格(上、下、左、右)和周围的任一棋子一次,到达新的合法状态。

目标测试:比较当前状态和目标状态的格局是否一致。

路径消耗:每一步的耗散值为1,因此整个路径的耗散值是从起始状态到目标状态的棋子移动的总步数。

1.3 解决方案介绍(原理)对于八数码问题的解决,首先要考虑是否有答案。

每一个状态可认为是一个1×9的矩阵,问题即通过矩阵的变换,是否可以变换为目标状态对应的矩阵?由数学知识可知,可计算这两个有序数列的逆序值,如果两者都是偶数或奇数,则可通过变换到达,否则,这两个状态不可达。

这样,就可以在具体解决问题之前判断出问题是否可解,从而可以避免不必要的搜索。

如果初始状态可以到达目标状态,那么采取什么样的方法呢?常用的状态空间搜索有深度优先和广度优先。

广度优先是从初始状态一层一层向下找,直到找到目标为止。

深度优先是按照一定的顺序前查找完一个分支,再查找另一个分支,以至找到目标为止。

广度和深度优先搜索有一个很大的缺陷就是他们都是在一个给定的状态空间中穷举。

这在状态空间不大的情况下是很合适的算法,可是当状态空间十分大,且不预测的情况下就不可取了。

他的效率实在太低,甚至不可完成。

由于八数码问题状态空间共有9!个状态,对于八数码问题如果选定了初始状态和目标状态,有9!/2个状态要搜索,考虑到时间和空间的限制,在这里采用A*算法作为搜索策略。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验报告一、实验问题八数码问题求解二、实验软件VC6.0 编程语言或其它编程语言三、实验目的1. 熟悉人工智能系统中的问题求解过程;2. 熟悉状态空间的盲目搜索和启发式搜索算法的应用;3. 熟悉对八数码问题的建模、求解及编程语言的应用。

四、实验数据及步骤(一、)实验内容八数码问题:在3×3的方格棋盘上,摆放着1到8这八个数码,有1个方格是空的,其初始状态如图1所示,要求对空格执行空格左移、空格右移、空格上移和空格下移这四个操作使得棋盘从初始状态到目标状态。

2 83 1 2 31 4 8 47 6 5 7 6 5(a) 初始状态(b) 目标状态图1 八数码问题示意图(二、)基本数据结构分析和实现1.结点状态我采用了struct Node数据类型typedef struct _Node{int digit[ROW][COL];int dist; // distance between one state and the destination一个表和目的表的距离int dep; // the depth of node深度// So the comment function = dist + dep.估价函数值int index; // point to the location of parent父节点的位置} Node; 2.发生器函数定义的发生器函数由以下的四种操作组成:(1)将当前状态的空格上移Node node_up;Assign(node_up, index);//向上扩展的节点int dist_up = MAXDISTANCE;(2)将当前状态的空格下移Node node_down;Assign(node_down, index);//向下扩展的节点int dist_down = MAXDISTANCE;(3)将当前状态的空格左移Node node_left;Assign(node_left, index);//向左扩展的节点int dist_left = MAXDISTANCE;(4)将当前状态的空格右移Node node_right;Assign(node_right, index);//向右扩展的节点int dist_right = MAXDISTANCE;通过定义结点状态和发生器函数,就解决了8数码问题的隐式图的生成问题。

接下来就是搜索了。

3.图的搜索策略经过分析,8数码问题中可采用的搜速策略共有:1.广度优先搜索、2.深度优先搜索、2.有界深度优先搜索、4.最好优先搜索、5.局部择优搜索,一共五种。

其中,广度优先搜索法是可采纳的,有界深度优先搜索法是不完备的,最好优先和局部择优搜索法是启发式搜索法。

实验时,采用了广度(宽度)优先搜索来实现。

(三、)广度(宽度)优先搜索原理1. 状态空间盲目搜索——宽度优先搜索其基本思想是,从初始节点开始,向下逐层对节点进形依次扩展,并考察它是否为目标节点,再对下层节点进行扩展(或搜索)之前,必须完成对当层的所有节点的扩展。

再搜索过程中,未扩展节点表OPEN中的节点排序准则是:先进入的节点排在前面,后进入的节点排在后面。

其搜索过程如图(1)所示。

图2、宽度优先搜索示意图2. 宽度优先算法如下:步1 把初始结点S0放入OPEN表中步2 若OPEN表为空,则搜索失败,问题无解步3 取OPEN表中最前面的结点N放在CLOSE表中,并冠以顺序编号n步4 若目标结点Sg=N,则搜索成功,问题有解步5 若N无子结点,则转步2步6 扩展结点N,将其所有子结点配上指向N的放回指针,依次放入OPEN表的尾部,转步23.宽度优先算法流程图图3、宽度优先算法流程图4.8数码难题用宽度优先搜索所生成的搜索树如图4。

搜索树上的所有节点都标记它们所对应的状态描述,每个节点旁边的数字表示节点扩展的顺序(按顺时针方向移动空格)。

图中有26个节点,也就是源程序运行结果。

22 23 24 25 26图4.八数码题宽度优先搜索树五、实验结果及分析上机试验时,,经多次程序调试,最后得一下结果。

此结果所得节点(状态图)很多 ,可知宽度优先搜索的盲目性很大,当目标节点距离初始节点较远时,就会产生大量的无用节点,搜索效率低。

但是,只要问题有解,用宽度优先搜索总可以找到它的解。

8 3 0 2 1 4 7 6 5 8 8 3 2 0 4 7 6 5 1 2 3 8 0 4 7 6 5 2 8 3 7 1 4 6 5 0 2 8 3 7 0 4 6 1 5图5.程序运行结果六、结论人工智能搜索可分为盲目搜索和启发式搜索。

盲目搜索算法有宽度优先算法、深度优先算法(有界深度优先算法),启发式搜索算法有A算法、A*算法。

本实验采用的是宽度优先(广度优先)算法,这种算法是按预定的控制策略进行,在搜素的过程中所获得的信息不用来改进控制策略。

由于搜索总是按预定的路线进行,没有考虑问题本身的特性,这种缺乏问题求解的针对性,需要进行全方位的搜索,而没有选择最优的搜索路径。

所以图4宽度优先搜索树及程序运行结果图5得到的节点(状态图)很多,而解路径为1-3-8-16-26,其它节点是没有用的节点,搜索效率很低。

通过这次实验更加熟悉状态空间的宽度优先搜索、深度优先搜索和启发式搜索算法及计算机语言对常用数据结构如链表、队列等的描述应用。

学到了不少知识。

七、源程序及注释#include <iostream>#include <ctime>#include <vector>using namespace std;const int ROW = 3;//行数const int COL = 3;//列数const int MAXDISTANCE = 10000;//最多可以有的表的数目const int MAXNUM = 10000;typedef struct _Node{int digit[ROW][COL];int dist; // distance between one state and the destination一个表和目的表的距离int dep; // the depth of node深度// So the comment function = dist + dep.估价函数值int index; // point to the location of parent父节点的位置} Node;Node src, dest;// 父节表目的表vector<Node> node_v; // store the nodes存储节点bool isEmptyOfOPEN() //open表是否为空{for (int i = 0; i < node_v.size(); i++) {if (node_v[i].dist != MAXNUM)return false;}return true;}bool isEqual(int index, int digit[][COL]) //判断这个最优的节点是否和目的节点一样{for (int i = 0; i < ROW; i++)for (int j = 0; j < COL; j++) {if (node_v[index].digit[i][j] != digit[i][j])return false;}return true;}ostream& operator<<(ostream& os, Node& node){for (int i = 0; i < ROW; i++) {for (int j = 0; j < COL; j++)os << node.digit[i][j] << ' ';os << endl;}return os;}void PrintSteps(int index, vector<Node>& rstep_v)//输出每一个遍历的节点深度遍历{rstep_v.push_back(node_v[index]);index = node_v[index].index;while (index != 0){rstep_v.push_back(node_v[index]);index = node_v[index].index;}for (int i = rstep_v.size() - 1; i >= 0; i--)//输出每一步的探索过程cout << "Step " << rstep_v.size() - i<< endl << rstep_v[i] << endl;}void Swap(int& a, int& b){int t;t = a;a = b;b = t;}void Assign(Node& node, int index){for (int i = 0; i < ROW; i++)for (int j = 0; j < COL; j++)node.digit[i][j] = node_v[index].digit[i][j];}int GetMinNode() //找到最小的节点的位置即最优节点{int dist = MAXNUM;int loc; // the location of minimize nodefor (int i = 0; i < node_v.size(); i++){if (node_v[i].dist == MAXNUM)continue;else if ((node_v[i].dist + node_v[i].dep) < dist) {loc = i;dist = node_v[i].dist + node_v[i].dep;}}return loc;}bool isExpandable(Node& node){for (int i = 0; i < node_v.size(); i++) {if (isEqual(i, node.digit))return false;}return true;}int Distance(Node& node, int digit[][COL]){int distance = 0;bool flag = false;for(int i = 0; i < ROW; i++)for (int j = 0; j < COL; j++)for (int k = 0; k < ROW; k++) {for (int l = 0; l < COL; l++) {if (node.digit[i][j] == digit[k][l]) {distance += abs(i - k) + abs(j - l);flag = true;break;}elseflag = false;}if (flag)break;}return distance;}int MinDistance(int a, int b){return (a < b ? a : b);}void ProcessNode(int index){int x, y;bool flag;for (int i = 0; i < ROW; i++) {for (int j = 0; j < COL; j++) {if (node_v[index].digit[i][j] == 0){x =i; y = j;flag = true;break;}else flag = false;}if(flag)break;}Node node_up;Assign(node_up, index);//向上扩展的节点int dist_up = MAXDISTANCE;if (x > 0){Swap(node_up.digit[x][y], node_up.digit[x - 1][y]); if (isExpandable(node_up)){dist_up = Distance(node_up, dest.digit);node_up.index = index;node_up.dist = dist_up;node_up.dep = node_v[index].dep + 1;node_v.push_back(node_up);}}Node node_down;Assign(node_down, index);//向下扩展的节点int dist_down = MAXDISTANCE;if (x < 2){Swap(node_down.digit[x][y], node_down.digit[x + 1][y]); if (isExpandable(node_down)){dist_down = Distance(node_down, dest.digit);node_down.index = index;node_down.dist = dist_down;node_down.dep = node_v[index].dep + 1;node_v.push_back(node_down);}}Node node_left;Assign(node_left, index);//向左扩展的节点int dist_left = MAXDISTANCE;if (y > 0){Swap(node_left.digit[x][y], node_left.digit[x][y - 1]);if (isExpandable(node_left)){dist_left = Distance(node_left, dest.digit);node_left.index = index;node_left.dist = dist_left;node_left.dep = node_v[index].dep + 1;node_v.push_back(node_left);}}Node node_right;Assign(node_right, index);//向右扩展的节点int dist_right = MAXDISTANCE;if (y < 2){Swap(node_right.digit[x][y], node_right.digit[x][y + 1]);if (isExpandable(node_right)){dist_right = Distance(node_right, dest.digit);node_right.index = index;node_right.dist = dist_right;node_right.dep = node_v[index].dep + 1;node_v.push_back(node_right);}}node_v[index].dist = MAXNUM;}int main() // 主函数{int number;cout << "Input source:" << endl;for (int i = 0; i < ROW; i++)//输入初始的表for (int j = 0; j < COL; j++) {cin >> number;src.digit[i][j] = number;}src.index = 0;src.dep = 1;cout << "Input destination:" << endl;//输入目的表for (int m = 0; m < ROW; m++)for (int n = 0; n < COL; n++) {cin >> number;dest.digit[m][n] = number;}node_v.push_back(src);//在容器的尾部加一个数据cout << "Search..." << endl;clock_t start = clock();while (1){if (isEmptyOfOPEN()){cout << "Cann't solve this statement!" << endl;return -1;}else{int loc; // the location of the minimize node最优节点的位置loc = GetMinNode();if(isEqual(loc, dest.digit)){vector<Node> rstep_v;cout << "Source:" << endl;cout << src << endl;PrintSteps(loc, rstep_v);cout << "Successful!" << endl;cout << "Using " << (clock() - start) / CLOCKS_PER_SEC<< " seconds." << endl;break;}elseProcessNode(loc);}}return 0;}十五数码问题的截图(对行和列数进行修改):。

相关文档
最新文档