《人工智能基础》实验报告-实验名称:启发式搜索算法

合集下载

人工智能实验报告

人工智能实验报告

人工智能九宫格重移——搜索成员:赵春杰 2009210665羊森 2009210653黄鑫 2009210周成兵 2009210664王素娟 20092106441.问题描述:八数码问题也称为九宫问题。

在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同。

棋盘上还有一个空格,与空格相邻的棋子可以移到空格中。

要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤。

所谓问题的一个状态就是棋子在棋盘上的一种摆法。

棋子移动后,状态就会发生改变。

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

2.九宫重移有无答案检查(逆序数)我们把每个9宫格横向展开,如第一个123456789,我们把左边数大于右边数的组数称为这个九宫格的逆序数,显然123456789的逆序数为0;考虑横向平移,那么逆序数的增量为2或0或-2;纵向平移,逆序数的增量为4或0或-4;但147258369的逆序数为奇数。

所以147258369是无解的情况。

由此也可以类推当将9宫格展开后,如果数据序列的逆序数为奇数,则此数据序列对应的九宫格是无解的。

3.BFS算法队列: Queue open = new Queue();存放待扩展的节点List: List<Bfstr> closed = new List<Bfstr>();存放已被扩展过的节点ArrayList map = new ArrayList();//存放答案HashTale: Hashtable table = new Hashtable();构造哈希表以方便查找3.1.BFS算法介绍广度优先搜索算法BFS基本思想:从图中某顶点v出发,逐层对节点进行拓展,并考察是否为目标节点,在第n层节点没有全部扩展并考察前,不对第n+1层节点进行扩展。

人工智能实验报告-八数码 (1)

人工智能实验报告-八数码 (1)

《人工智能》实验一题目实验一 启发式搜索算法1. 实验内容:使用启发式搜索算法求解8数码问题。

⑴ 编制程序实现求解8数码问题A *算法,采用估价函数()()()()w n f n d n p n ⎧⎪=+⎨⎪⎩, 其中:()d n 是搜索树中结点n 的深度;()w n 为结点n 的数据库中错放的棋子个数;()p n 为结点n 的数据库中每个棋子与其目标位置之间的距离总和。

⑵ 分析上述⑴中两种估价函数求解8数码问题的效率差别,给出一个是()p n 的上界的()h n 的定义,并测试使用该估价函数是否使算法失去可采纳性。

2. 实验目的熟练掌握启发式搜索A *算法及其可采纳性。

3.数据结构与算法设计 该搜索为一个搜索树。

为了简化问题,搜索树节点设计如下:typedef struct Node//棋盘{//节点结构体int data[9];double f,g;struct Node * parent; //父节点}Node,*Lnode;int data[9]; 数码数组:记录棋局数码摆放状态。

struct Chess * Parent; 父节点:指向父亲节点。

下一步可以通过启发搜索算法构造搜索树。

1、局部搜索树样例:2、搜索过程搜索采用广度搜索方式,利用待处理队列辅助,逐层搜索(跳过劣质节点)。

搜索过程如下:(1)、把原棋盘压入队列;(2)、从棋盘取出一个节点;(3)、判断棋盘估价值,为零则表示搜索完成,退出搜索;(4)、扩展子节点,即从上下左右四个方向移动棋盘,生成相应子棋盘;(5)、对子节点作评估,是否为优越节点(子节点估价值小于或等于父节点则为优越节点),是则把子棋盘压入队列,否则抛弃;(5)、跳到步骤(2);3、算法的评价完全能解决简单的八数码问题,但对于复杂的八数码问题还是无能为力。

现存在的一些优缺点。

1、可以改变数码规模(N),来扩展成N*N的棋盘,即扩展为N数码问题的求解过程。

<!--[if !supportLists]-->2、<!--[endif]-->内存泄漏。

人工智能实验报告

人工智能实验报告

****大学人工智能基础课程实验报告(2011-2012学年第一学期)启发式搜索王浩算法班级: *********** 学号: ********** 姓名: ****** 指导教师: ******成绩:2012年 1 月 10 日实验一 启发式搜索算法1. 实验内容:使用启发式搜索算法求解8数码问题。

⑴ 编制程序实现求解8数码问题A *算法,采用估价函数()()()()w n f n d n p n ⎧⎪=+⎨⎪⎩, 其中:()d n 是搜索树中结点n 的深度;()w n 为结点n 的数据库中错放的棋子个数;()p n 为结点n 的数据库中每个棋子与其目标位置之间的距离总和。

⑵ 分析上述⑴中两种估价函数求解8数码问题的效率差别,给出一个是()p n 的上界的()h n 的定义,并测试使用该估价函数是否使算法失去可采纳性。

2. 实验目的熟练掌握启发式搜索A *算法及其可采纳性。

3. 实验原理使用启发式信息知道搜索过程,可以在较大的程度上提高搜索算法的时间效率和空间效率;启发式搜索的效率在于启发式函数的优劣,在启发式函数构造不好的情况下,甚至在存在解的情形下也可能导致解丢失的现象或者找不到最优解,所以构造一个优秀的启发式函数是前提条件。

4.实验内容 1.问题描述在一个3*3的九宫格 里有1至8 八个数以及一个空格随机摆放在格子中,如下图:初始状态 目标状态现需将图一转化为图二的目标状态,调整的规则为:每次只能将空格与其相邻的一个数字进行交换。

实质是要求给出一个合法的移动步骤,实现从初始状态到目标状态的转变。

2.算法分析 (1)解存在性的讨论对于任意的一个初始状态,是否有解可通过线性代数的有关理论证明。

按数组存储后,算出初始状态的逆序数和目标状态的逆序数,若两者的奇偶性一致,则表明有解。

(2)估价函数的确定通过对八数码的特性的研究,找出一个相对好的函数,f(n)=d(n)+h(n)其中h(n)=2*compare(n)+3*S(n);d(n)为已搜索的深度;(compare(n)为当前节点与目标结点相同位置不相同的个数,S(n)为当前节点的无序度。

人工智能的启发式算法

人工智能的启发式算法

人工智能的启发式算法
遗传算法是一种受自然选择启发的优化算法,它通过模拟生物
进化的过程,利用交叉、变异和选择等操作来搜索最优解。

模拟退
火算法则模拟金属退火的过程,通过接受较差解的概率来跳出局部
最优解,从而更有可能找到全局最优解。

蚁群算法则模拟蚂蚁寻找
食物的过程,利用信息素和启发式规则来引导搜索。

遗传规划算法
结合了遗传算法和规划方法,用于解决优化问题和规划问题。

启发式算法在解决NP难题和大规模优化问题时具有一定的优势,因为它们能够在可接受的时间内找到较好的解。

然而,启发式算法
并不保证找到最优解,而是找到一个较好的近似解。

因此,在应用
启发式算法时,需要权衡计算资源和解的质量。

除了上述提到的算法之外,还有许多其他启发式算法,它们在
不同的问题领域和应用场景中发挥着重要作用。

启发式算法的发展
也是一个活跃的研究领域,研究者们不断提出新的算法和改进现有
算法,以应对不断变化的复杂问题。

总的来说,启发式算法在人工
智能领域具有重要意义,为解决现实世界中的复杂问题提供了一种
有效的方法。

(完整版)启发式搜索算法

(完整版)启发式搜索算法

人工智能基础实验报告实验名称:八数码问题姓名:张俊学号:2220092333指导老师:邓安生启发式搜索算法1. 实验内容:使用启发式搜索算法求解8数码问题。

⑴ 编制程序实现求解8数码问题A *算法,采用估价函数()()()()w n f n d n p n ⎧⎪=+⎨⎪⎩, 其中:()d n 是搜索树中结点n 的深度;()w n 为结点n 的数据库中错放的棋子个数;()p n 为结点n 的数据库中每个棋子与其目标位置之间的距离总和。

⑵ 分析上述⑴中两种估价函数求解8数码问题的效率差别,给出一个是()p n 的上界的()h n 的定义,并测试使用该估价函数是否使算法失去可采纳性。

2. 实验目的熟练掌握启发式搜索A *算法及其可采纳性。

3. 实验原理八数码问题是在3行和3列构成的九宫棋盘上放置数码为1到8的8个棋盘,剩下一个空格的移动来不断改变棋盘的布局,求解这类问题的方法是:给定初始布局(即初始状态)和目标布局(即目标状态),定义操作算子的直观方法是为每个棋牌制定一套可能的走步》上,下,左,右四种移动,再根据所定义的启发式搜索函数在搜索过程中选择最合适的操作算子,得到最优的路径。

4.源代码#include <iomanip>#include <stdlib.h>#include <time.h>#include <iostream>#include <stdio.h>#include <conio.h>#include <math.h>//以上为C++源文件using namespace std;static int space=0;int target[9];class EightNum//定义一个EightNum 类{public:int num[9];int f;//初始状态与目标状态相比,棋子错放个数int deap;//深度int evalfun;//状态的估价值EightNum *parent;//以下为类内成员函数的声明EightNum(int nnum[9]);int get_evalfun();int get_deapfun();void eval_func(int id);int Canspread(int n);void Spreadchild(int n);void getnum(int num1[9]);void setnum(int num1[9]);void show(void);int operator ==(EightNum& NewEightN);int operator ==(int num2[9]);int Shownum();};//-----------------------以下为EightNum类成员函数定义-----------------// class Stack{private:EightNum * eightnum;public:Stack * next;EightNum * Minf();EightNum * Belong(EightNum * suc);void Putinto(EightNum * suc);};EightNum::EightNum(int nnum[9]){//此函数功能为:初始化num[];for(int i=0;i<9;i++)num[i]=nnum[i];f=0;deap=0;parent=NULL;}int EightNum::get_evalfun(){return evalfun;}int EightNum::get_deapfun(){return deap;}void EightNum::eval_func(int id){//此函数为估价函数int i,qifa;qifa=0;switch(id){case 1:{for(i=0;i<9;i++){if(num[i]!=target[i])qifa++;}break;}case 2:{int j, h1,h2;for(i=0;i<9;i++){for(j=0;j<9;j++){if(num[j]==i)h1=j;if(target[j]==i)h2=j;}qifa+=(int)(fabs((double)(h1/3 - h2/3)) + fabs((double)(h1%3 - h2%3)));}break;}case 3:{int j, h1,h2;for(i=0;i<9;i++){for(j=0;j<9;j++){if(num[j]==i)h1=j;if(target[j]==i)h2=j;}qifa+=(int)(fabs((double)(h1/3 - h2/3)) + fabs((double)(h1%3 - h2%3)));}qifa=3*qifa;break;}default :break;}f=qifa;if(this->parent==NULL) deap=0;else deap=this->parent->deap+1;evalfun=deap+f;}int EightNum::Canspread(int n){//判断空格"0"可否移动int i,flag = 0;for(i = 0;i < 9;i++)if(this->num[i] == 0)break;switch(n){case 1:if(i/3 != 0)flag = 1;break;case 2:if(i/3 != 2)flag = 1;break;case 3:if(i%3 != 0)flag = 1;break;case 4:if(i%3 != 2)flag = 1;break;default:break;}return flag ;}void EightNum::Spreadchild(int n){//扩展child节点的子节点int i,loc,qifa;for(i = 0;i < 9;i++)this->num[i] = this->parent->num[i];for(i = 0;i < 9;i++)if(this->num[i] == 0)break;if(n==0)loc = i%3+(i/3 - 1)*3;else if(n==1)loc = i%3+(i/3 + 1)*3;else if(n==2)loc = i%3-1+(i/3)*3;elseloc = i%3+1+(i/3)*3;qifa = this->num[loc];this->num[i] = qifa;this->num[loc] = 0;}void EightNum::getnum(int num1[9]){ for(int i=0;i<9;i++)num1[i]=num[i];}void EightNum::setnum(int num1[9]){ for(int i=0;i<9;i++)num[i]=num1[i];}void EightNum::show(){//输出函数for(int i=0;i<9;i++){cout<<num[i]<<" ";if((i+1)%3==0)cout<<"\n";}cout<<"--------------------";}int EightNum::Shownum(){if(this == NULL)return 0;else{int n = this->parent->Shownum();this->show();cout<<endl;return n+1;}}int EightNum::operator ==(EightNum& NewEightN){int compere=1;for(int i=0;i<9;i++)if(num[i]!=NewEightN.num[i]){compere=0;break;}if(compere==0) return 0;else return 1;}//-----------------------以下为分函数的定义---------------------////判断是否有解的函数int solve(int num[9],int target[9]){int i,j;int num_con=0,tar_con=0;for(i=0;i<9;i++)for(j=0;j<i;j++){if(num[j]<num[i] && num[j]!=0)num_con++;if(target[j]<target[i] && target[j]!=0)tar_con++;}num_con=num_con%2;tar_con=tar_con%2;if((num_con==0 && tar_con==0)||(num_con==1 && tar_con==1))return 1;elsereturn 0;}EightNum * Stack::Minf(){Stack * qifa =this->next;Stack * min = this->next;Stack * minp = this;EightNum * minx;while(qifa->next != NULL){if((qifa->next->eightnum->get_evalfun()) < (min->eightnum->get_evalfun())){min = qifa->next;minp = qifa;}qifa = qifa->next;}minx = min->eightnum;qifa = minp->next;minp->next = minp->next->next;free(qifa);return minx;}//判断节点是否属于OPEN表或CLOSED表EightNum * Stack::Belong(EightNum * suc){Stack * qifa = this-> next ;if(qifa == NULL)return NULL;while(qifa != NULL){if(suc==qifa->eightnum)return qifa ->eightnum;qifa = qifa->next;}return NULL;}//把节点存入OPEN 或CLOSED 表中void Stack::Putinto(EightNum * suc){Stack * qifa;qifa =(Stack *) malloc(sizeof(Stack));qifa->eightnum = suc;qifa->next = this->next;this->next = qifa;}int BelongProgram(EightNum * suc ,Stack *Open ,Stack *Closed ,EightNum goal,int m ){EightNum * qifa = NULL;int flag = 0;if((Open->Belong(suc) != NULL) || (Closed->Belong(suc) != NULL)){if(Open->Belong(suc) != NULL) qifa = Open->Belong(suc);else qifa = Closed->Belong(suc);flag=1;}else{Open->Putinto(suc);suc->eval_func(m);}return flag;}//扩展后继节点总函数void Spread(EightNum * suc, Stack * Open, Stack * Closed, EightNum goal,int m){int i;EightNum * child;for(i = 0; i < 4; i++){if(suc->Canspread(i+1)){space++;child = (EightNum *) malloc(sizeof(EightNum));child->parent = suc;child->Spreadchild(i);child->eval_func(m);if(BelongProgram(child, Open, Closed, goal,m)) //判断子节点是否属于OPEN或CLOSED表free(child);}}}//执行函数EightNum * Process(EightNum * org, EightNum goal, Stack * Open, Stack * Closed,int m){while(1){if(Open->next == NULL)return NULL;EightNum * minf =Open->Minf();Closed->Putinto(minf);if((*minf)==goal)return minf;Spread(minf, Open, Closed, goal,m);}}//------------------------A*算法搜索函数----------------------//void A(int id,EightNum start,EightNum Target){EightNum * result;space=0;float time;Stack *Open = (Stack *) malloc(sizeof(Stack));Open->next = NULL;Stack *Closed = (Stack *) malloc(sizeof(Stack));Closed->next = NULL;clock_t startt,finisht;startt=clock();//开始时间start.eval_func(id);Open->Putinto(&start);result = Process(&start, Target, Open, Closed,id); //进行剩余的操作cout<<"\n搜索过程:\n"<<result->Shownum()<<endl;finisht=clock();time=(float)(finisht-startt);cout<<endl<<id<<"算法处理结果:所耗时间:";cout<<time;cout<<"ms, ";cout<<"所耗空间:";cout<<space;cout<<"块, "<<endl<<endl;}//-----------------------------主函数-----------------------------//int main(void)//主函数{int i,j;int flag;int num[9];int error;do{error=0;cout<<"请输入八数码问题的初始状态(0代表空格,“棋子”间用空格隔开):"<<endl;for(i=0;i<9;i++){flag=0;cin>>num[i];for(j=0;j<i;j++)if(num[j]==num[i])flag=1;if(num[i]<0||num[i]>8||flag==1){error++;}}if(error!=0)cout<<"输入数据错误!请重新输入!"<<endl;}while(error!=0);//输入八数码问题的初始状态(0代表空格,“棋子”间用空格隔开);int error1;do{error1=0;cout<<"请输入新的目标状态(用0代表空格,“棋子”间用空格隔开):"<<endl;for(i=0;i<9;i++){flag=0;cin>>target[i];for(j=0;j<i;j++)if(target[j]==target[i])flag=1;if(target[i]<0||target[i]>9||flag==1){error1++;}}if(error1!=0)cout<<"输入数据错误!请重新输入!"<<endl;}while(error1!=0);//输入八数码问题的目标状态(用0代表空格,中间用空格隔开);EightNum start(num),Target(target);int m=solve(num,target);//判断初始状态到目标状态是否有解,有解返回1,误解返回0;if(m==0){cout<<"此状态无解!"<<endl;return 0;}int id=0;while(id!=3){cout<<"1. 错放的棋子个数为;\n2.每个棋子与目标位置之间的距离总和为;"<<endl;cout<<"3.结束,退出程序!"<<endl;cout<<"\n请选择功能,分别输入“1”“2”“3”进行选择:"<<endl;cin>>id;switch(id){case 1:{cout<<"错放的棋子个数结果为:\n(以下逐一展示搜索过程:)"<<endl;A(1,start,Target);break;}case 2:{cout<<"每个棋子与其目标位置之间的距离总和为:\n(以下逐一展示搜索过程:)"<<endl;A(2,start,Target);break;}default: break;}}cout<<"啊啊….程序结束!!";}实验截图实验中遇到的问题1:开始程序只能运行一种方式即按照错位个数搜索,后经过查找相关资料,修改后可程序可进行选择,两种方法结合在一起根据选择运行。

人工智能课内实验报告2

人工智能课内实验报告2

人工智能课内实验报告(二) ----重排九宫(A*算法)一、实验目的1. 熟悉启发式搜索的思想,加深对各种图搜索策略概念的理解;2. 运用搜索算法重排九宫使之从初始状态到底目标状态,并求解最短路径。

二、实验内容在三种不同的搜索算法中任选一种实现重排九宫。

这三种方法分别是:A*算法、有界深度优先搜索和广度优先搜索。

具体描述:在一个3×3的方格棋盘上放置8个标有1、2、3、4、5、6、7、8数字的将牌,留下一个空格(用0表示)。

规定:与空格相邻的将牌可以移入空格。

要求:寻找一条从初始状态到目标状态的将牌移动路线。

三、实验原理启发式搜索是在搜索中加入了与问题有关的启发性信息,用以指导搜索朝着最有希望的方向前进,加速问题的求解过程并找到最优解。

A*算法是一种启发式搜索。

广度优先搜索按照“先扩展出的节点先被考察”的原则进行搜索。

深度优先搜索按照“后扩展出的节点先被考察”的原则进行搜索。

有界深度优先搜索的原则与深度优先搜索相同,但是它规定了深度限界,使搜索不得无限制地向纵深方向发展。

(一)搜索的一般描述:1. 把初始节点S0放入OPEN表,并建立目前只包含S0的图,记为G;2. 检查OPEN表是否为空,若为空则问题无解,退出;3. 把OPEN表的第一个节点取出放入CLOSE表,并计该节点为n;4. 考察节点n是否为目标节点。

若是,则求得了问题的解,退出;5. 扩展节点n,生成一组子节点。

把其中不是节点n先辈的那些子节点记做集合M,并把这些子节点作为节点n的子节点加入G中;6. 针对M中子节点的不同情况,分别进行如下处理:(1)对于那些未曾在G中出现过的M成员设置一个指向父节点(即节点n)的指针,并把它们放入OPEN表;(不在OPEN表)(2)对于那些先前已经在G中出现过的M成员,确定是否需要修改它指向父节点的指针;(在OPEN表中)(3)对于那些先前已在G中出现并且已经扩展了的M成员,确定是否需要修改其后继节点指向父节点的指针;(在CLOSE表中)7. 按某种搜索策略对OPEN表中的节点进行排序;8. 转第2步。

人工智能实验报告 八数码问题

人工智能实验报告 八数码问题

实验一 启发式搜索算法姓名:徐维坚 学号:2220103484 日期:2012/6/29一、实验目的:熟练掌握启发式搜索A *算法及其可采纳性。

二、实验内容:使用启发式搜索算法求解8数码问题。

1) 编制程序实现求解8数码问题A *算法,采用估价函数()()()()w n f n d n p n ⎧⎪=+⎨⎪⎩, 其中:()d n 是搜索树中结点n 的深度;()w n 为结点n 的数据库中错放的棋子个数;()p n 为结点n 的数据库中每个棋子与其目标位置之间的距离总和。

2) 分析上述⑴中两种估价函数求解8数码问题的效率差别,给出一个是()p n 的上界 的()h n 的定义,并测试使用该估价函数是否使算法失去可采纳性。

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

在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同。

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

要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤。

所谓问题的一个状态就是棋子在棋盘上的一种摆法。

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

2. 原理描述:2.1 有序搜索算法:(1)原理:在搜索过程中,OPEN 表中节点按照其估价函数值以递增顺序排列,选择OPEN 表中具有最小估价函数值的节点作为下一个待扩展的节点,这种搜索方法称为有序搜索。

在本例中,估价函数中的)(n g 取节点深度)(n d ,)(n h 为节点n 的状态与目标状态之间错放的个数,即函数)(n ω。

(2)算法描述:① 把起始节点S 放到OPEN 表中,并计算节点S 的)(S f ;② 如果OPEN 是空表,则失败退出,无解;③ 从OPEN 表中选择一个f 值最小的节点i 。

如果有几个节点值相同,当其中有一个 为目标节点时,则选择此目标节点;否则就选择其中任一个节点作为节点i ;④ 把节点i 从 OPEN 表中移出,并把它放入 CLOSED 的已扩展节点表中;⑤ 如果i 是个目标节点,则成功退出,求得一个解;⑥ 扩展节点i ,生成其全部后继节点。

人工智能-启发式搜索

人工智能-启发式搜索

实验报告姓名:***学号:**********班级:软件二班实验名称:启发式搜索课程名称:人工智能实验日期:2015.11.09实验环境:Visual C++实验目的以及内容:1、实验内容:使用启发式搜索算法求解八数码问题。

(1)编制程序实现求解八数码问题A*算法,采用估价函数其中:d(n)是搜索树中节点n的深度;w(n)为节点n的数据库中错放的棋子个数;p(n)为节点n的数据库中的每个棋子与其目标位置之间的距离的总和。

(2)分析上述(1)中的两种估价函数求解八数码问题的效率差别,给出一个是p(n)的上界的h(n)的定义,并测试使用该估价函数是否使算法失去可采纳性。

2、实验目的:熟练的掌握启发式搜索A*算法及其可采纳性。

3. 实验原理:八数码问题是在3行和3列构成的九宫棋盘上放置数码为1到8的8个棋盘,剩下一个空格的移动来不断改变棋盘的布局,求解这类问题的方法是:给定初始布局(即初始状态)和目标布局(即目标状态),定义操作算子的直观方法是为每个棋牌制定一套可能的走步》上,下,左,右四种移动,再根据所定义的启发式搜索函数在搜索过程中选择最合适的操作算子,得到最优的路径。

代码:#include"stdio.h"#define num 3void show(int begin[num][num]){for(int i = 0; i < num; i++){for(int j = 0; j < num; j++)printf("%d ", begin[i][j]);printf("\n");}printf("\n");}void exchange(int begin[num][num], int row_one, int column_one, int row_two, int column_two){int temp;temp = begin[row_two][column_two] ;begin[row_two][column_two] = begin[row_one][column_one];begin[row_one][column_one] = temp;}int judge(int begin[num][num], int end[num][num]){int count=0;for(int i = 0; i < num; i++)for(int j = 0; j < num; j++){if(begin[i][j] == end[i][j] && end[i][j] != 0)count++;}return count;}int yidong(int begin[num][num], int end[num][num], int right, int jishu, int ji_shu[50][3][3], int biaoji, int row, int column){int temp_zhi;show(begin);if(jishu >= 20)return 0;int node;int temp;for(int q=0; q<jishu; q++){node = 1;for(int w=0; w<num && node; w++)for(int r=0; r<num && node; r++)if(ji_shu[q][w][r] != begin[w][r])node = 0;if(node == 1){return 0;}}for(int i = 0; i < num; i++)for(int j = 0; j < num; j++)ji_shu[jishu][i][j] = begin[i][j];if(right == num * num - 1)return 1;if(row > 0 && biaoji != 0){exchange(begin, row - 1, column, row , column);temp = judge(begin, end);if(temp < right)exchange(begin, row - 1, column, row , column);else if(temp >= right){temp_zhi = yidong(begin, end, temp, jishu+1, ji_shu, 2, row-1, column);if( temp_zhi == 1)return 1;exchange(begin, row - 1, column, row , column);}}if(column > 0 && biaoji != 1){exchange(begin, row, column - 1, row , column);temp = judge(begin, end);if(temp < right)exchange(begin, row, column - 1, row , column);else if(temp >= right){temp_zhi = yidong(begin, end, temp, jishu+1, ji_shu ,3, row, column -1);if(temp_zhi == 1)return 1;exchange(begin, row, column - 1, row , column);}}if(row < num-1 && biaoji != 2){exchange(begin, row + 1, column, row , column);temp = judge(begin, end);if(temp < right)exchange(begin, row + 1, column, row , column);else if(temp >= right){temp_zhi =yidong(begin, end, temp, jishu+1, ji_shu, 0, row+1, column);if(temp_zhi == 1)return 1;exchange(begin, row + 1, column, row , column);}}if(column < num-1 && biaoji != 3){exchange(begin, row, column + 1, row , column);temp = judge(begin, end);if(temp < right)exchange(begin, row, column + 1, row , column);else if(temp >= right){temp_zhi = yidong(begin, end, temp, jishu+1, ji_shu, 1, row, column+1);if(temp_zhi == 1)return 1;exchange(begin, row, column + 1, row , column);}}return 0;}void shuru(int begin[][num],int blank[]){int temp, node, zero = 0;for (int i = 0; i < num; i++)for(int j = 0; j < num; j++){node = 1;printf("请输入第%d行,第%d列的元素的值:", i+1, j+1);scanf("%d", &temp);for (int q = 0; q <= i && node == 1; q++)for (int w = 0; w < j; w++)if(temp == begin[q][w]){printf("输入重复,请重新输入\n");node = 0;j--;break;}if(temp < 0 || temp > num*num-1){printf("请输入从%d到%d的数\n", zero, num*num-1);node = 0;j--;}if(node == 1){if(temp == 0){blank[0] = i;blank[1] = j;}begin[i][j] = temp;}}}int main(){int jishu = 0, ji_shu[50][3][3];int row;int column;int begin[num][num], blank[2],count=1;int end[num][num] = {1, 2, 3, 8, 0, 4, 7, 6, 5};printf ("-------8数码游戏开始!--------\n");shuru(begin, blank);row = blank[0];column = blank[1];if(yidong (begin, end,judge(begin,end),jishu,ji_shu,4,row,column) == 0)printf("\n此8数码的问题可能无解!");elseshow(begin);getchar();getchar();return 0;}实验截图:实验总结:1、A*搜索算法:取g(n)=d(n),h(n)=w(n),其中w(n)表示以目标为基准,结点n的状态中每一个数码牌与其目标位置之间的距离(不考虑夹在其间的数码牌)的总和,由于从结点n转换成目标结点至少需要w(n)步,所以对任意n,恒有w(n) ≤h*(n)。

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

实验名称:启发式搜索算法1、实验环境Visual C++ 6.02、实验目的和要求(复述问题)使用启发式算法求解8数码问题(1)编制程序实现求解8数码问题A*算法,采用估价函数f(n)=d(n)+p(n)其中:d(n)是搜索树中结点n的深度;w(n)为节点n的数据库中错放的旗子个数;p(n)为结点n的数据库中每个棋子与其目标位置之间的距离总和。

(2)分析上述(1)中两种估价函数求解8数码问题的效率差别,给出一个是p(n)的上界h(n)的定义,并测试该估价函数是否使算法失去可采纳性。

实验目的:熟练掌握启发式搜索A*算法及其可采纳性。

3、解题思路、代码3.1解题思路八数码问题的求解算法(1)盲目搜索宽度优先搜索算法、深度优先搜索算法(2)启发式搜索启发式搜索算法的基本思想是:定义一个评价函数f,对当前的搜索状态进行评估,找出一个最有希望的节点来扩展。

先定义下面几个函数的含义:f*(n)=g*(n)+h*(n) (1)式中g*(n)表示从初始节点s到当前节点n的最短路径的耗散值;h*(n)表示从当前节点n到目标节点g的最短路径的耗散值,f*(n)表示从初始节点s经过n到目标节点g 的最短路径的耗散值。

评价函数的形式可定义如(2)式所示:f(n)=g(n)+h(n) (2)其中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) (3)成立,则称好h(x)为h*(x)的下界,它表示某种偏于保守的估计。

采用h*(x)的下界h(x)为启发函数的A算法,称为A*算法针对八数码问题启发函数设计如下:F(n)=d(n)+p(n) (4)其中A*算法中的g(n)根据具体情况设计为d(n),意为n节点的深度,而h(n)设计为p(n),意为放错的数码与正确的位置距离之和。

由于实际情况中,一个将牌的移动都是单步进行的,没有交换拍等这样的操作。

所以要把所有的不在位的将牌,移动到各自的目标位置上,至少要移动从他们各自的位置到目标位置的距离和这么多次,所以最有路径的耗散值不会比该值小,因此该启发函数h(n)满足A*算法的条件。

3.2代码#include<stdio.h>#include<stdlib.h>#include<math.h>//八数码状态对应的节点结构体struct Node{int s[3][3];//保存八数码状态,0代表空格int f,g;//启发函数中的f和g值struct Node * next;struct Node *previous;//保存其父节点};int open_N=0; //记录Open列表中节点数目//八数码初始状态int inital_s[3][3]={2,8,3,1,6,4,7,0,5};//八数码目标状态int final_s[3][3]={1,2,3,8,0,4,7,6,5};//------------------------------------------------------------------------//添加节点函数入口,方法:通过插入排序向指定表添加//------------------------------------------------------------------------void Add_Node( struct Node *head, struct Node *p){struct Node *q;if(head->next)//考虑链表为空{ q = head->next;if(p->f < head->next->f){//考虑插入的节点值比链表的第一个节点值小p->next = head->next;head->next = p;}else {while(q->next)//考虑插入节点x,形如a<= x <=b{if((q->f < p->f ||q->f == p->f) && (q->next->f > p->f || q->next->f == p->f)){ p->next = q->next;q->next = p;break;}q = q->next;}if(q->next == NULL) //考虑插入的节点值比链表最后一个元素的值更大q->next = p;}}else head->next = p;}//------------------------------------------------------------------------//删除节点函数入口//------------------------------------------------------------------------void del_Node(struct Node * head, struct Node *p ){struct Node *q;q = head;while(q->next){if(q->next == p){q->next = p->next;p->next = NULL;if(q->next == NULL) return;// free(p);}q = q->next;}}//------------------------------------------------------------------------//判断两个数组是否相等函数入口//------------------------------------------------------------------------int equal(int s1[3][3], int s2[3][3]){int i,j,flag=0;for(i=0; i< 3 ; i++)for(j=0; j< 3 ;j++)if(s1[i][j] != s2[i][j]){flag = 1; break;}if(!flag)return 1;else return 0;}//------------------------------------------------------------------------//判断后继节点是否存在于Open或Closed表中函数入口//------------------------------------------------------------------------int exit_Node(struct Node * head,int s[3][3], struct Node *Old_Node){struct Node *q=head->next;int flag = 0;while(q)if(equal(q->s,s)) {flag=1;Old_Node->next = q;return 1;}else q = q->next;if(!flag) return 0;}//------------------------------------------------------------------------//计算p(n)的函数入口//其中p(n)为放错位的数码与其正确的位置之间距离之和//具体方法:放错位的数码与其正确的位置对应下标差的绝对值之和//------------------------------------------------------------------------int wrong_sum(int s[3][3]){int i,j,fi,fj,sum=0;for(i=0 ; i<3; i++)for(j=0; j<3; j++){for(fi=0; fi<3; fi++)for(fj=0; fj<3; fj++)if((final_s[fi][fj] == s[i][j])){sum += fabs(i - fi) + fabs(j - fj);break;}}return sum;}//------------------------------------------------------------------------//获取后继结点函数入口//检查空格每种移动的合法性,如果合法则移动空格得到后继结点//------------------------------------------------------------------------int get_successor(struct Node * BESTNODE, int direction, struct Node *Successor)//扩展BESTNODE,产生其后继结点SUCCESSOR{int i,j,i_0,j_0,temp;for(i=0; i<3; i++)for(j=0; j<3; j++)Successor->s[i][j] = BESTNODE->s[i][j];//获取空格所在位置for(i=0; i<3; i++)for(j=0; j<3; j++)if(BESTNODE->s[i][j] == 0){i_0 = i; j_0 = j;break;}switch(direction){case 0: if((i_0-1)>-1 ){temp = Successor->s[i_0][j_0];Successor->s[i_0][j_0] = Successor->s[i_0-1][j_0];Successor->s[i_0-1][j_0] = temp;return 1;}else return 0;case 1: if((j_0-1)>-1){temp = Successor->s[i_0][j_0];Successor->s[i_0][j_0] = Successor->s[i_0][j_0-1];Successor->s[i_0][j_0-1] = temp;return 1;}else return 0;case 2: if( (j_0+1)<3){temp = Successor->s[i_0][j_0];Successor->s[i_0][j_0] = Successor->s[i_0][j_0+1];Successor->s[i_0][j_0+1] = temp;return 1;}else return 0;case 3: if((i_0+1)<3 ){temp = Successor->s[i_0][j_0];Successor->s[i_0][j_0] = Successor->s[i_0+1][j_0];Successor->s[i_0+1][j_0] = temp;return 1;}else return 0;}}//------------------------------------------------------------------------//从OPen表获取最佳节点函数入口//------------------------------------------------------------------------struct Node * get_BESTNODE(struct Node *Open){return Open->next;}//------------------------------------------------------------------------//输出最佳路径函数入口//------------------------------------------------------------------------void print_Path(struct Node * head){struct Node *q, *q1,*p;int i,j,count=1;p = (struct Node *)malloc(sizeof(struct Node));//通过头插法变更节点输出次序p->previous = NULL;q = head;while(q){q1 = q->previous;q->previous = p->previous;p->previous = q;q = q1;}q = p->previous;while(q){if(q == p->previous)printf("八数码的初始状态:\n");else if(q->previous == NULL)printf("八数码的目标状态:\n");else printf("八数码的中间态%d\n",count++);for(i=0; i<3; i++)for(j=0; j<3; j++){printf("%4d",q->s[i][j]);if(j == 2)printf("\n");}printf("f=%d, g=%d\n\n",q->f,q->g);q = q->previous;}}//------------------------------------------------------------------------//A*子算法入口:处理后继结点//------------------------------------------------------------------------void sub_A_algorithm(struct Node * Open, struct Node * BESTNODE, struct Node * Closed,struct Node *Successor){struct Node * Old_Node = (struct Node *)malloc(sizeof(struct Node));Successor->previous = BESTNODE;//建立从successor返回BESTNODE的指针Successor->g = BESTNODE->g + 1;//计算后继结点的g值//检查后继结点是否已存在于Open和Closed表中,如果存在:该节点记为old_Node,比较后继结点的g值和表中old_Node节点//g值,前者小代表新的路径比老路径更好,将Old_Node的父节点改为BESTNODE,并修改其f,g值,后者小则什么也不做。

相关文档
最新文档