人工智能(A星算法)
A星算法求八数码问题实验报告

A星算法求八数码问题实验报告人工智能实验报告实验名称:八数码问题姓名:xx学号:2012210xxxx计算机学院2014年1月14日一.实验目的掌握A*的思想,启发式搜索,来求解在代价最小的情况下将九宫格从一个状态转为另状态的路径。
二.实验内容给定九宫格的初始状态,要求在有限步的操作内,使其转化为目标状态,且所得到的解是代价最小解(2 8 31 6 47 0 52 8 31 6 47 0 5三、A*算法思想:1、思想:A*算法是一种静态路网中求解最短路最有效的直接搜索方法。
估价值与实际值越接近,估价函数取得就越好2、原理:估价函数公式表示为: f(n)=g(n)+h(n),其中 f(n) 是从初始点经由节点n到目标点的估价函数,g(n) 是在状态空间中从初始节点到n节点的实际代价,h(n) 是从n到目标节点最佳路径的估计代价。
保证找到最短路径(最优解的)条件,关键在于估价函数h(n)的选取:估价值h(n)<= n到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。
但能得到最优解。
并且如果h(n)=d(n),即距离估计h(n)等于最短距离,那么搜索将严格沿着最短路径进行此时的搜索效率是最高的。
如果估价值>实际值,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。
四、算法流程:Heuristic_Search(启发式搜索)While是从未拓展表中删N为目是,输出路径否,生成n的所有子状态Case:此子状Case:此子状Case:此子状计算该子状记录比已有记录比已有返回五、关键技术:1、使用了CreateChild()函数,求得了任意未拓展九宫格的扩展结点,便于拓展子空间,搜索所有情况。
关键代码:bool CreateChild(NOExtend ns[],NOExtend ne){int i,j,k=0;for(i=0;i<3;i++){for(j=0;j<3;j++){if(ne.cur_sudoku.num[i][j]==0){ //寻找九宫格空缺所在的坐标if(i-1>=0){ //将空格向上移动CopySudoku(ns[k].cur_sudoku,ne.cur_sudo ku);//先把未改变的九宫格复制给九宫格数组的某一元素ns[k].cur_sudoku.num[i][j]=ne.cur_sudoku.num[i-1][j];//然后仅改变此二维九宫格的两项值即可ns[k].cur_sudoku.num[i-1][j]=0;ns[k].dx=1;k++;}if(j+1<=2){ //将空格向右移动CopySudoku(ns[k].cur_sudoku,ne.cur_sudo ku);ns[k].cur_sudoku.num[i][j]=ns[k].cur_su doku.num[i][j+1];ns[k].cur_sudoku.num[i][j+1]=0;ns[k].dx=1;k++;}if(i+1<=2){ //将空格向下移动CopySudoku(ns[k].cur_sudoku,ne.cur_sudo ku);ns[k].cur_sudoku.num[i][j]=ns[k].cur_su doku.num[i+1][j];ns[k].cur_sudoku.num[i+1][j]=0;ns[k].dx=1;k++;}if(j-1>=0){ //将空格向左移动CopySudoku(ns[k].cur_sudoku,ne.cur_sudo ku);ns[k].cur_sudoku.num[i][j]=ns[k].cur_su doku.num[i][j-1];ns[k].cur_sudoku.num[i][j-1]=0;ns[k].dx=1;k++;}return 1;}}}return 0;2、用启发式搜索函数寻找求解路径,运用了A*算法的思想,能够更快的求解出最优解。
a星算法求解八数码问题python

a星算法求解八数码问题python一、介绍八数码问题是一种经典的智力游戏,也是人工智能领域中的经典问题之一。
在这个问题中,有一个3×3的棋盘,上面摆着1至8这8个数字和一个空格,初始状态和目标状态都已知。
要求通过移动数字,将初始状态变换成目标状态。
其中空格可以和相邻的数字交换位置。
为了解决这个问题,我们可以使用A*算法。
本文将详细介绍如何用Python实现A*算法来求解八数码问题。
二、A*算法简介A*算法是一种启发式搜索算法,常用于寻找最短路径或最优解等问题。
它基于Dijkstra算法,并加入了启发式函数来加速搜索过程。
在A*算法中,每个节点都有两个估价值:g值和h值。
g值表示从起点到该节点的实际代价,h值表示从该节点到目标节点的估计代价。
启发式函数f(n) = g(n) + h(n) 表示从起点到目标节点的估计总代价。
A*算法采用优先队列来保存待扩展的节点,并按照f(n)值从小到大排序。
每次取出队头元素进行扩展,并将扩展出来的新节点按照f(n)值插入队列中。
当扩展出目标节点时,算法结束。
三、八数码问题的状态表示在八数码问题中,每个状态都可以表示为一个3×3的矩阵。
我们可以用一个一维数组来表示这个矩阵,其中0表示空格。
例如,初始状态可以表示为[2, 8, 3, 1, 6, 4, 7, 0, 5],目标状态可以表示为[1, 2, 3, 8, 0, 4, 7, 6, 5]。
四、A*算法求解八数码问题的步骤1.将初始状态加入优先队列中,并设置g值和h值为0。
2.从队头取出一个节点进行扩展。
如果该节点是目标节点,则搜索结束;否则,将扩展出来的新节点加入优先队列中。
3.对于每个新节点,计算g值和h值,并更新f(n)值。
如果该节点已经在优先队列中,则更新其估价值;否则,将其加入优先队列中。
4.重复第2步至第3步直到搜索结束。
五、Python实现以下是用Python实现A*算法求解八数码问题的代码:```import heapqimport copy# 目标状态goal_state = [1,2,3,8,0,4,7,6,5]# 启发式函数:曼哈顿距离def h(state):distance = 0for i in range(9):if state[i] == 0:continuerow = i // 3col = i % 3goal_row = (state[i]-1) // 3goal_col = (state[i]-1) % 3distance += abs(row - goal_row) + abs(col - goal_col)return distance# A*算法def A_star(start_state):# 初始化优先队列和已访问集合queue = []visited = set()# 将初始状态加入优先队列中,并设置g值和h值为0heapq.heappush(queue, (h(start_state), start_state, 0))while queue:# 取出队头元素进行扩展f, state, g = heapq.heappop(queue)# 如果该节点是目标节点,则搜索结束;否则,将扩展出来的新节点加入优先队列中。
启发式搜索A星算法

启发式搜索——初识A*算法A*在游戏中有它很典型的用法,是人工智能在游戏中的代表。
A*算法在人工智能中是一种典型的启发式搜索算法,为了说清楚A*算法,先说说何谓启发式算法。
一、何谓启发式搜索算法在说它之前先提提状态空间搜索。
状态空间搜索,如果按专业点的说法,就是将问题求解过程表现为从初始状态到目标状态寻找这个路径的过程。
通俗点说,就是在解一个问题时,找到一个解题的过程,应用这个过程可以从求解的开始得到问题的结果。
由于求解问题的过程中分支有很多,主要是求解过程中求解条件的不确定性、不完备性造成的,使得求解的路径很多,这样就构成了一个图,我们说这个图就是状态空间。
问题的求解实际上就是在这个图中找到一条路径可以从开始到结果。
这个寻找的过程就是状态空间搜索。
常用的状态空间搜索有深度优先和广度优先。
广度优先是从初始状态一层一层向下找,直到找到目标为止。
深度优先是按照一定的顺序,先查找完一个分支,再查找另一个分支,直至找到目标为止。
这两种算法在数据结构书中都有描述,可以参看这些书得到更详细的解释。
前面说的广度和深度优先搜索有一个很大的缺陷就是:他们都是在一个给定的状态空间中穷举。
这在状态空间不大的情况下是很合适的算法,可是当状态空间十分大,且不可预测的情况下就不可取了。
他们的效率实在太低,甚至不可完成。
在这里就要用到启发式搜索了。
启发式搜索就是在状态空间中搜索时,对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直至找到目标。
这样可以省略大量无谓的搜索路径,提高了效率。
在启发式搜索中,对位置的估价是十分重要的。
采用了不同的估价可以有不同的效果。
我们先看看估价是如何表示的。
启发中的估价是用估价函数表示的,如:f(n) = g(n) + h(n)其中f(n)是节点n的估价函数,g(n)是在状态空间中从初始节点到n节点的实际代价,h(n)是从n节点到目标节点最佳路径的估计代价。
在这里主要是h(n)体现了搜索的启发信息,因为g(n)是已知的。
实验四:A星算法求解迷宫问题实验

实验四:A*算法求解迷宫问题实验之樊仲川亿创作一、二、实验目的熟悉和掌握启发式搜索的定义、估价函数和算法过程,并利用A*算法求解迷宫问题,理解求解流程和搜索顺序。
三、实验内容迷宫问题可以表述为:一个二维的网格,0暗示点可走,1暗示点不成以走,点用(x,y)暗示,寻找从某一个给定的起始单元格出发,经由行相邻或列相邻的单元格(可以通过的),最终可以到达目标单元格的、所走过的单元格序列。
在任一个单元格中,都只能看到与它邻近的4个单元格(如果位于底边,则只有3个;位于4个角上,则只有2个是否能通过)。
A*算法是人工智能中的一种搜索算法,是一种启发式搜索算法,它不需遍历所有节点,只是利用包含问题启发式信息的评价函数对节点进行排序,使搜索方向朝着最有可能找到目标并发生最优解的方向。
它的独特之处是检查最短路径中每个可能的节点时引入了全局信息,对当前节点距终点的距离做出估计,并作为评价节点处于最短路线上的可能性的度量。
A*算法中引入了评估函数,评估函数为:f(n)=g(n)+h (n)其中:n是搜索中遇到的任意状态。
g(n)是从起始状态到n的代价。
h(n)是对n到目标状态代价的启发式估计。
即评估函数f ( n) 是从初始节点到达节点n 处已经付出的代价与节点n 到达目标节点的接近程度估价值的总和。
这里我们定义n点到目标点的最小实际距离为h(n)*,A*算法要满足的条件为:h(n)<=h(n)*迷宫走的时候只能往上下左右走,每走一步,代价为1,这里我们采取的估价函数为当前节点到目标节点的曼哈顿距离,即:h(n)=|end.x – n.x|+ |end.y – n.y|这里end暗示迷宫的目标点,n暗示当前点,很明显这里h (n)<=h(n)*。
g(n)容易暗示,即每走一步的代价是1,所以利用f(n)=g (n)+h(n)这种战略,我们可以不竭地迫近目标点,从而找到问题的解。
时间复杂度:m行n列的迷宫矩阵实现算法的时间复杂度为O(m*n).实验结果:实验源码:#include <queue>#include <vector>#include <iostream>using namespace std;int direc[4][2]={{0,1},{-1,0},{0,-1},{1,0}};enum Flag{SEAL,OPEN,UNVISITED};typedef struct node{int _x,_y; //节点坐标(x,y)int _G; //实际已开销Gint _H; //探测将开销Hint _F; //优先级_F=_G+_H struct node *pre; //前驱顶点}Queue_Node;typedef struct{Flag flag;Queue_Node *point;}Seal;class A_Star{public://构造函数A_Star(){input();}~A_Star(){for(int i=1;i<=_len;++i){for(int j=1;j<=_wid;++j){if(_seal[i][j].point!=NULL){delete _seal[i][j].point;}}}for(i=0;i<=_len;++i){delete []_seal[i];delete []_maze[i];}delete []_seal;delete []_maze;}void input(){cout<<"输入: 迷宫左边长,上边宽! 例如:30 20"<<endl;cin>>_len>>_wid;_seal=new Seal*[_len+1];_maze=new unsigned char*[_len+1];for(int i=0;i<=_len;++i){_seal[i]=new Seal[_wid+1];_maze[i]=new unsigned char[_wid+1];}cout<<"从下一行开始输入迷宫信息:"<<endl;for( i=1;i<=_len;++i){for(int j=1;j<=_wid;++j){cin>>_maze[i][j];_seal[i][j].flag=UNVISITED;_seal[i][j].point=NULL;}}cout<<"输入起点坐标,目标点坐标,例如:1 1 30 20"<<endl;cin>>_sx>>_sy>>_ex>>_ey;if(_maze[_sx][_sy]=='1'||_maze[_ex][_ey]=='1'||bound (_sx,_sy)==false||bound(_ex,_ey)==false){cout<<"不成能存在这样的情况!"<<endl;return;}cout<<"调用A*算法打印结果如下:"<<endl;A();}//A*核心算法void A(){//源点放入开放列表Queue_Node *p_node=new Queue_Node;p_node->pre=NULL;p_node->_H=get_H(_sx,_sy);p_node->_G=0;p_node->_x=_sx;p_node->_y=_sy;p_node->_F=p_node->_H+p_node->_G;_open.push(p_node);_seal[_sx][_sy].flag=OPEN;_seal[_sx][_sy].point=p_node;while(!_open.empty()){p_node=_open.top();_open.pop();int x=p_node->_x;int y=p_node->_y;_seal[x][y].flag=SEAL;for(int i=0;i<4;++i){int tx=x+direc[i][0];int ty=y+direc[i][1];if(bound(tx,ty)==false||_maze[tx][ty]=='1'||_seal[tx ][ty].flag==SEAL){continue;}if(_seal[tx][ty].flag==UNVISITED){if(tx==_ex&&ty==_ey){print(p_node);cout<<"("<<tx<<","<<ty<<")"<<endl;cout<<"总共走了:"<<p_node->_F<<"步"<<endl;return;}Queue_Node *temp=new Queue_Node;_seal[tx][ty].flag=OPEN;_seal[tx][ty].point=temp;temp->pre=p_node;temp->_G=p_node->_G+1;temp->_x=tx;temp->_y=ty;temp->_H=get_H(tx,ty);temp->_F=temp->_G+temp->_H;_open.push(temp);}else{Queue_Node*temp=_seal[tx][ty].point;if(p_node->_G+1<temp->_G){temp->_G=p_node->_G+1;temp->pre=p_node;temp->_F=temp->_G+temp->_H;}}}}cout<<"没有从("<<_sx<<","<<_sy<<")--->"<<"("<<_ex<<","<<_ey<<")的路径"<<endl;}//打印路径void print(Queue_Node *p){if(p==NULL){return;}print(p->pre);cout<<"("<<p->_x<<","<<p->_y<<"),";}bool bound(int x,int y){return (x<=_len)&&(x>=1)&&(y<=_wid)&&(y>=1);}int get_H(int x,int y){return ab(x-_ex)+ab(y-_ey);}int ab(int i){return i<0 ? -i:i;}private:struct cmp{bool operator()(Queue_Node *n1,Queue_Node *n2){return n1->_F>n2->_F;}};priority_queue<Queue_Node *,vector<Queue_Node *>,cmp> _open;//最小堆(开放列表)int _len,_wid;//迷宫左边长,上边宽int _sx,_sy,_ex,_ey;Seal **_seal;//动态开辟封闭列表unsigned char **_maze;//迷宫地图};int main(){A_Star test;return 0;}四、实验目的通过这次实验,使我对启发式搜索算法有了更进一步的理解,特别是估计函数h(n)所起到的巨大重用。
A星算法中文详解

A星算法中文详解A*算法是一种图算法,用于找到从起始节点到目标节点的最短路径。
它是一种启发式算法,根据每个节点的估计成本来进行。
本文将详细介绍A*算法的原理、步骤和实现。
A* 算法的基本思想是在 Dijkstra 算法的基础上引入启发式函数,目的是在过程中尽量选择离目标节点更接近的路径。
启发式函数通常使用两个估计函数的和:g(n) 是从起始节点到当前节点的实际代价,h(n) 是当前节点到目标节点的估计代价。
通过评估 f(n) = g(n) + h(n) 的值,选择 f(n) 最小的节点作为下一步的节点。
这样,方向就会倾向于更接近目标节点的路径。
A*算法的步骤如下:1. 创建两个空集合:Open 集合和 Closed 集合。
Open 集合存储待考虑的节点,Closed 集合存储已经考虑过的节点。
2. 将起始节点添加到 Open 集合中,并初始化 g(n) 和 h(n) 的值。
3. 从 Open 集合中选择 f(n) 最小的节点作为当前节点,并将其移出 Open 集合,放入 Closed 集合中。
4.对当前节点的相邻节点进行遍历:- 如果相邻节点已经在 Closed 集合中,则忽略它。
- 如果相邻节点不在 Open 集合中,将其添加到 Open 集合,并计算g(n) 和 h(n) 的值。
- 如果相邻节点已经在 Open 集合中,计算经过当前节点到达相邻节点的 g(n) 值。
如果计算得到的 g(n) 值更小,则更新相邻节点的 g(n) 值。
5. 重复步骤 3 和 4,直到找到目标节点或者 Open 集合为空。
如果Open 集合为空且没有找到目标节点,则表示无法到达目标节点。
6.如果找到目标节点,可以通过回溯从目标节点到起始节点的路径。
路径上的节点可以通过每个节点的父节点指针找到。
以上就是A*算法的详细步骤。
A*算法的时间复杂度取决于启发式函数的选择和问题的规模。
通常情况下,A*算法的时间复杂度为O(b^d),其中b是分支因子,d是目标节点的最短路径长度。
A星算法

很早以前就写过A*算法,现在把概念写出来供参考寻路一般主要有深度优先和广度优先及启发式探索算法。
a. 深度优先:一般是深度优先是按照一定的顺序前查找完一个分支,再查找另一个分支,直到找到目标或到达步数为止。
b.广度优先一般是找周围所有点记录下来,然后在对每个点找它们周围所有未找过的点,然后再如此循环下去直到找到目标为止。
c. 启发式启发式搜索一般是对每个搜索位置进行评估,找到最好的位置,再从这个位置如此循环进行搜索直到目标。
启发中的估价是用估价函数表示的:f(n) = g(n) + h(n)其中f(n) 是节点n的估价函数,g(n)是从初始点到n结点的实际代价,h(n)是从n结点到目标点最佳路径的估价。
如果公式中的h(n)总是=0, 也即不进行估价,那么就是广度优先,现在的A*算法一般都使用了启发式函数,对于普通的A*算法通常使用当前结点到目标结点的距离来计算h。
关于启发式要考虑的启发因素还有类似于一些地形属性如泥士地走慢点等也可考虑在内。
晕死, 后来发现原来我早之前已经写过这个文章, 见我旧blog:/blog/cns!8E578E7901A88369!444.entry内容如下:寻路备忘录寻路备忘录一.深度优先搜索(DFS)按照一定顺序(如左上右下)能走则走(这就是深度两字的来源),就象一个瞎子走迷宫一样:1.选定一个方向一直走2.碰壁后退一步,再重复1的步骤.缺点:a.在很少障碍的空地图上若跨出的第一步顺序不对时寻路挺费时;b.找到的不一定是最短路径优点:算法所用内存较少.二.广度优先搜索(BFS)1.先在开始位置测试周围一格所能走的路,并记录周围的通路格子;2.然后依次选择周围的通路格子位置重复1步骤.这就象一个水波扩散一样,这就是广度两字的来源.缺点:寻路所用内存较大优点:能保证找到最短路径三.启发式搜索:A*就是常用的一种启发式算法.作法如下:1.选路,这会用到一个叫估价函数的东东F(X),其中F(X)=G(X)+H(X);式中的G(X)一般是已经搜索的步数,而H(X)则是一个从当前节点到目标节点估计函数,一般可用当前节点到目标节点的距离来作比较.2.走路,碰到不通路时,在所有所记录的通路中重新选择一条路来走,即重复1.优点:速度快并且所占内存不多。
启发式搜索A星算法

启发式搜索——初识A*算法A*在游戏中有它很典型的用法,是人工智能在游戏中的代表。
A*算法在人工智能中是一种典型的启发式搜索算法,为了说清楚A*算法,先说说何谓启发式算法。
一、何谓启发式搜索算法在说它之前先提提状态空间搜索。
状态空间搜索,如果按专业点的说法,就是将问题求解过程表现为从初始状态到目标状态寻找这个路径的过程。
通俗点说,就是在解一个问题时,找到一个解题的过程,应用这个过程可以从求解的开始得到问题的结果。
由于求解问题的过程中分支有很多,主要是求解过程中求解条件的不确定性、不完备性造成的,使得求解的路径很多,这样就构成了一个图,我们说这个图就是状态空间。
问题的求解实际上就是在这个图中找到一条路径可以从开始到结果。
这个寻找的过程就是状态空间搜索。
常用的状态空间搜索有深度优先和广度优先。
广度优先是从初始状态一层一层向下找,直到找到目标为止。
深度优先是按照一定的顺序,先查找完一个分支,再查找另一个分支,直至找到目标为止。
这两种算法在数据结构书中都有描述,可以参看这些书得到更详细的解释。
前面说的广度和深度优先搜索有一个很大的缺陷就是:他们都是在一个给定的状态空间中穷举。
这在状态空间不大的情况下是很合适的算法,可是当状态空间十分大,且不可预测的情况下就不可取了。
他们的效率实在太低,甚至不可完成。
在这里就要用到启发式搜索了。
启发式搜索就是在状态空间中搜索时,对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直至找到目标。
这样可以省略大量无谓的搜索路径,提高了效率。
在启发式搜索中,对位置的估价是十分重要的。
采用了不同的估价可以有不同的效果。
我们先看看估价是如何表示的。
启发中的估价是用估价函数表示的,如:f(n) = g(n) + h(n)其中f(n)是节点n的估价函数,g(n)是在状态空间中从初始节点到n节点的实际代价,h(n)是从n节点到目标节点最佳路径的估计代价。
在这里主要是h(n)体现了搜索的启发信息,因为g(n)是已知的。
a星算法原理

a星算法原理1. 基本思路A* 算法是基于图模型的搜索算法,其中图由若干个节点和连接这些节点的边组成。
搜索的目标是在图上寻找一条从起点到终点的最优路径。
A* 算法的基本思路如下:(1)首先将起点加入open列表(即待搜索的节点列表),定义一个空的close列表(即已搜索的节点列表)。
(2)从open列表中取出F值最小的节点,将其加入close列表。
(3)若该节点为终点,则搜索完成,否则将它的相邻节点加入open列表。
(4)对于所有加入open列表的节点,计算它们的F值,并更新它们的父节点。
(5)重复步骤2-4,直到open列表为空或者找到终点。
F值由G值和H值组成:F =G + HG值表示从起点到该节点的实际代价,H值表示从该节点到终点的启发式估价(即一个估计值,不一定是实际值,但必须保证不小于实际值)。
1.启发式估价函数必须保证不小于实际代价。
2.启发式估价函数应该尽量接近实际代价,否则会影响搜索效率。
3.启发式估价函数不能产生死循环或者走回头路的情况。
2. 估价函数的选取(1)曼哈顿距离曼哈顿距离指两点之间横纵坐标差的绝对值之和。
曼哈顿距离是一种比较简单的启发式估价函数,它适用于只能沿水平或竖直方向移动的情况。
曼哈顿距离在斜着走的时候有一定的误差,不够精确。
(2)欧几里得距离欧几里得距离指两点之间的直线距离。
欧几里得距离是一种比较精确的启发式估价函数,它适用于可以在任何方向上移动的情况。
欧几里得距离会导致算法不够稳定,容易出现死循环的情况。
(3)切比雪夫距离(4)自定义估价函数如果以上的估价函数不能满足需要,还可以根据具体需求自定义估价函数。
自定义估价函数要满足启发式估价函数的基本要求,并且尽量简单易实现。
3. A*算法的优缺点(1)A*算法具有较高的搜索效率,并且能够找到最优解。
(2)A*算法能够通过启发式估价函数优化搜索路径,从而减少搜索量。
(1)A*算法的搜索效率和搜索结果非常依赖于所选择的估价函数,不同的估价函数可能产生完全不同的搜索结果。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
人工智能
6)扩展节点n,生成其后继结点集M,在G中,n的祖先不能在M中。在G中安 置M的成员,使他们成为n的后继。 7)从M的每一个不在G中的成员建立一个指向n的指针(例如,既不在OPEN中, 也不在CLOSED中)。把M1的这些成员加到OPEN中。对M的每一个已在OPEN中或 CLOSED中的成员m,如果到目前为止找到的到达m的最好路径通过n,就把它 的指针指向n。对已在CLOSED中的M的每一个成员,重定向它在G中的每一个 后继,以使它们顺着到目前为止发现的最好路径指向它们的祖先。 8)按递增f*值,重排OPEN(相同最小f*值可根据搜索树中的最深节点来解决)。 9)返回第3步。 在第7步中,如果搜索过程发现一条路径到达一个节点的代价比现存的路径 代价低,就要重定向指向该节点的指针。已经在CLOSED中的节点子孙的重定向保 存了后面的搜索结果,但是可能需要指数级的计算代价。
人工智能 7
} }
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;
实验步骤
算法流程图
开始
读入棋局初始状态
否 是否可解
是 初始状态加入 open 表
在 open 表中找到评价值最小的节点,作为当前结点 是 是目标节点 否
扩展新状态,把不重复的新状态加入 open 表中
当前结点从 open 表移除
输出结果
结束
2
人工智能
程序代码
#include <ቤተ መጻሕፍቲ ባይዱostream> #include <ctime> #include <vector> using namespace std;
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);
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);
1)生成一个只包含开始节点n0的搜索图G,把n0放在一个叫OPEN的列表上。 2)生成一个列表CLOSED,它的初始值为空。 3)如果OPEN表为空,则失败退出。 4)选择OPEN上的第一个节点,把它从OPEN中移入CLPSED,称该节点为n。 5)如果n是目标节点,顺着G中,从n到n0的指针找到一条路径,获得解决方 案,成功退出(该指针定义了一个搜索树,在第7步建立)。
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; //一个表和目的表的距离 int dep; // t 深度 int index; //节点的位置 } Node;
}
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++)
4
for (int j = 0; j < COL; j++) node.digit[i][j] = node_v[index].digit[i][j]; }
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;
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++)
void PrintSteps(int index, vector<Node>& rstep_v)//输出每一个遍历的 节点 深度遍历 { rstep_v.push_back(node_v[index]); index = node_v[index].index; while (index != 0) {
人工智能 6
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); } }
实验条件
1. Window NT/xp/7 及以上的操作系统 2. 内存在 512M 以上 3. CPU 在奔腾 II 以上
实验内容
1. 分别以 8 数码和 15 数码为例实际求解 A*算法 2. 画出 A*算法求解框图 3. 分析估价函数对搜索算法的影响 4. 分析 A*算法的特点
实验分析
1. A*算法基本步骤
人工智能
A*算法实验报告
实验目的
1.熟悉和掌握启发式搜索的定义、估价函数和算法过程 2. 学会利用 A*算法求解 N 数码难题 3. 理解求解流程和搜索顺序
实验原理
A*算法是一种有序搜索算法,其特点在于对估价函数的定义上。对于一般的 有序搜索,总是选择 f 值最小的节点作为扩展节点。因此,f 是根据需要找到一 条最小代价路径的观点来估算节点的,所以,可考虑每个节点 n 的估价函数值为 两个分量:从起始节点到节点 n 的代价以及从节点 n 到达目标节点的代价。
人工智能 5
flag = true; break; } else flag = 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++) {
int GetMinNode() //找到最小的节点的位置 即最优节点 { int dist = MAXNUM; int loc; // the location of minimize node for (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; } }