八数码难题 Matlab
人工智能8位数码难题的问题求解
#define DOWN 1
#define LEFT 2
#define RIGHT 3
#define Bit char
typedef struct maps
{
Bit detail[9];
int myindex; //记录自己节点在hash表中的位置
Bit position; //记录空格(0)在序列中的位置
实验软硬件要求:网络计算机,c++编程环境
实验内容、方法和步骤(可附页)
我们将八数码难题分布在3×3方格棋盘上,分别放置了标有数字1,2,3,4,5,6,7,8的八张牌,初始状态S0,目标状态如图所示,可以使用的操作有:空格上移,空格左移,空格右移,空格下移。我们将是用广度优先搜索算法来解决这一问题。
int newindex = Parent.myindex ;
Bit *p = Parent.detail;
switch(direct)
{
case UP :
{
newindex -= 3*40320 ;
newindex += ( p[ i - 2 ] > p[ i - 3 ]) ? ( Factorial[ p[ i - 3 ] ] ) : ( - Factorial[ p[ i - 2 ] ] );
}p,*PMap;
Map org; //初始状态
int EndIndex; //目标,上移,下移,左移,右移
int const derection[4] ={ -3 , 3 , -1 , 1 } ;
//可移动的四个方向
int const Factorial[9] = {40320 , 5040 , 720 , 120 , 24 , 6 , 2 , 1 , 1 };
8数码问题分析及程序代码
八数码问题1、问题描述所谓八数码问题是指:将分别标有数字1,2,3,…,8的八块正方形数码牌任意地放在一块3×3的数码盘上。
放牌时要求不能重叠。
于是,在3×3的数码盘上出现了一个空格。
现在要求按照每次只能将与空格相邻的数码牌与空格交换的原则,将任意摆放的数码盘逐步摆成某种特殊的排列。
2、问题分析首先,八数码问题包括一个初始状态(strat) 和 目标状态(goal),所谓解八数码问题就是在两个状态间寻找一系列可过渡状态(strat-> strat 1-> strat 2->...->goal )。
这个状态是否存在表示空格)图13、 数据结构 定义结构体Node 如下: typedef struct{int num[9];char cur_expension; //记录是否可以扩展,Y 代表可以扩展,N 代表不可以。
char Operate; //表示不可以执行的操作,'L'代表不能左移,'R'代表不能右移, //'U'代表不能上移,'D'代表不能下移,'C'代表可以任意移动。
int father; //记录父节点的下标。
}Node;Node state[MAXSIZE]; //将搜索过的状态存储于该数组中。
4、广度优先搜索广度优先搜索是指按节点的层次进行搜索,本层的节点没有搜索完毕时,不能对下层节点进行处理,即深度越小的节点越先得到扩展,也就是说先产生的节点先得以扩展处理,直至找到目标为止。
求解八数码问题的搜索过程:如图2所示,把所有可能的算符应用到开始节点(即空格上移、空格左移、空格右移、空格下移),图2只是演示了两个扩展结点,如此继续下去,直到发现目标节点。
图2 变量定义及函数说明:1 2 3 45 6 7 8 01 2 37 4 5 8 0 61 2 34 5 67 8 0#define SUM 100//限定只搜索前50步,50步以后如果仍然没有搜索到结果,认为无解。
八数码难题--Matlab
b1=zhao(a1); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [a1,b1]=zuo(a)[x,y]=find(a==0);a1=a;a1(x,y)=a(x,y-1);a1(x,y-1)=0;b1=zhao(a1); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [a1,b1]=you(a)[x,y]=find(a==0);a1=a;a1(x,y)=a(x,y+1);a1(x,y+1)=0;b1=zhao(a1); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function z=panduan(a)global E;global I;I=2;[x,y]=size(E);z=1;for i=1:yb=E{i};v=(b-a).^2;if sum(sum(v))==0z=0;break;endend %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function y=zhao(a)wan=[1 2 3;8 0 4;7 6 5];y=0;b=a-wan;for i=1:3for j=1:3if b(i,j)~=0y=y+1;endendend %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% global Eglobal Ia=[2 8 3;1 0 4;7 6 5];b=[1 2 3;8 0 4;7 6 5];I=1;E(1)={a};for i=2:20q=b-E{i};if sum(sum(q.^2))E(i)={kaka(E{i-1})};celldisp(E(i))elsebreak;endend %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [a1]=kaka(a)global I;global E;c=[2 8 3;1 0 4;7 6 5];E(1)={c};[x,y]=find(a==0);z=9;if x==1if y==1[x1,y1]=xia(a);if y1<zif panduan(x1)b=x1;z=y1;endend[x2,y2]=you(a);if y2<zif panduan(x2)b=x2;z=y2;endenda1=b;endif y==2[x1,y1]=xia(a);if y1<zif panduan(x1)z=y1;endend[x2,y2]=zuo(a);if y2<zif panduan(x2) b=x2;z=y2;endend[x3,y3]=you(a);if y3<zif panduan(x3) b=x3;z=y3;endenda1=b;endif y==3[x1,y1]=xia(a);if y1<zif panduan(x1) b=x1;z=y1;endend[x2,y2]=zuo(a);if y2<zif panduan(x2) b=x2;z=y2;endenda1=b;endendif x==2if y==1[x1,y1]=shang(a);if y1<zif panduan(x1) b=x1;endend[x2,y2]=xia(a);if y2<zif panduan(x2) b=x2;z=y2;endend[x3,y3]=you(a);if y3<zif panduan(x3) b=x3;z=y3;endenda1=b;endif y==2[x1,y1]=shang(a);if y1<zif panduan(x1); b=x1;z=y1;endend[x2,y2]=xia(a);if y2<zif panduan(x2); b=x2;z=y2;endend[x3,y3]=zuo(a);if y3<zif panduan(x3); b=x3;z=y3;endend[x4,y4]=you(a);if y4<z;if panduan(x4)z=y4;endenda1=b;endif y==3[x1,y1]=shang(a);if y1<zif panduan(x1) b=x1;z=y1;endend[x2,y2]=xia(a);if y2<zif panduan(x2) b=x2;z=y2;endend[x3,y3]=zuo(a);if y3<zif panduan(x3) b=x3;z=y3;endenda1=b;endendif x==3if y==1[x1,y1]=shang(a);if y1<zif panduan(x1) b=x1;z=y1;endend[x4,y4]=you(a);if y4<z;if panduan(x4) b=x4;endenda1=b;endif y==2[x1,y1]=shang(a);if y1<zif panduan(x1) b=x1;z=y1;endend[x3,y3]=zuo(a);if y3<zif panduan(x3) b=x3;z=y3;endend[x4,y4]=you(a);if y4<z;if panduan(x4) b=x4;z=y4;endenda1=b;endif y==3[x1,y1]=shang(a);if y1<zif panduan(x1) b=x1;z=y1;endend[x3,y3]=zuo(a);if y3<zif panduan(x3) b=x3;z=y3;endenda1=b;endendE(I)={a1};五、实验结论1、启发式搜索算法A*流程图和算法框图。
人工智能A星算法解决八数码难题程序代码
#include "Stdio.h"#include "Conio.h"#include "stdlib.h"#include "math.h"void Copy_node(struct node *p1,struct node *p2);void Calculate_f(int deepth,struct node *p);void Add_to_open(struct node *p);void Add_to_closed(struct node *p);void Remove_p(struct node *name,struct node *p);int Test_A_B(struct node *p1,struct node *p2);struct node * Search_A(struct node *name,struct node *temp); void Print_result(struct node *p);struct node // 定义8数码的节点状态{int s[3][3]; //当前8数码的状态int i_0; //当前空格所在行号int j_0; //当前空格所在列号int f; //当前代价值int d; //当前节点深度int h; //启发信息,采用数码"不在位"距离和struct node *father; //指向解路径上该节点的父节点struct node *next; //指向所在open或closed表中的下一个元素} ;struct node s_0={{2,8,3,1,6,4,7,0,5},2,1,0,0,0,NULL,NULL}; //定义初始状态struct node s_g={{1,2,3,8,0,4,7,6,5},1,1,0,0,0,NULL,NULL}; //定义目标状态struct node *open=NULL; //建立open表指针struct node *closed=NULL; //建立closed表指针int sum_node=0; //用于记录扩展节点总数//***********************************************************//********************** **********************//********************** 主函数开始**********************//********************** **********************//***********************************************************void main(){int bingo=0; //定义查找成功标志,bingo=1,成功struct node s; //定义头结点sstruct node *target,*n,*ls,*temp,*same; //定义结构体指针Copy_node(&s_0,&s); //复制初始状s_0态给头结点s Calculate_f(0,&s); //计算头结点的代价值Add_to_open(&s); //将头结点s放入open表while(open!=NULL) //只要open表不为空,进行以下循环{n=open; //n指向open表中当前要扩展的元素ls=open->next;Add_to_closed(n);open=ls; //将n指向的节点放入closed表中if(Test_A_B(n,&s_g)) //当前n指向节点为目标时,跳出程序结束;否则,继续下面的步骤{bingo=1;break;}elseif(n->j_0>=1) //空格所在列号不小于1,可左移{temp=n->father;if(temp!=NULL&&temp->i_0==n->i_0&&temp->j_0-1==n->j_0) //新节点与其祖父节点相同;else //新节点与其祖父节点不同,或其父节点为起始节点{temp=(struct node *)malloc(sizeof(struct node)); //给新节点分配空间Copy_node(n,temp); //拷贝n指向的节点状态temp->s[temp->i_0][temp->j_0]=temp->s[temp->i_0][temp->j_0-1]; //空格左移temp->s[temp->i_0][temp->j_0-1]=0;temp->j_0--;temp->d++;Calculate_f(temp->d,temp); //修改新节点的代价值temp->father=n; //新节点指向其父节点if(same=Search_A(closed,temp)) //在closed表中找到与新节点状态相同的节点{if(temp->f<same->f) //temp指向的节点,其代价比closed表中相同状态节点代价小,加入open表{Remove_p(closed,same); //从closed表中删除与temp指向节点状态相同的节点Add_to_open(temp);sum_node++;}else;}else if(same=Search_A(open,temp)) //在open表中找到与新节点状态相同的节点{if(temp->f<same->f) //temp指向的节点,其代价比open表中相同状态节点代价小,加入open表{Remove_p(open,same); //从open表中删除与temp指向节点状态相同的节点Add_to_open(temp);sum_node++;}else ;}else //新节点为完全不同的新节点,加入open表{Add_to_open(temp);sum_node++;}}}//end左移if(n->j_0<=1) //空格所在列号不大于1,可右移{temp=n->father;if(temp!=NULL&&temp->i_0==n->i_0&&temp->j_0+1==n->j_0) //新节点与其祖父节点相同;else //新节点与其祖父节点不同,或其父节点为起始节点{temp=(struct node *)malloc(sizeof(struct node)); //给新节点分配空间Copy_node(n,temp); //拷贝p指向的节点状态temp->s[temp->i_0][temp->j_0]=temp->s[temp->i_0][temp->j_0+1]; //空格右移temp->s[temp->i_0][temp->j_0+1]=0;temp->j_0++;temp->d++;Calculate_f(temp->d,temp); //修改新节点的代价值temp->father=n; //新节点指向其父节点if(same=Search_A(closed,temp)) //在closed表中找到与新节点状态相同的节点{if(temp->f<same->f) //temp指向的节点,其代价比closed表中相同状态节点代价小,加入open表{Remove_p(closed,same); //从closed表中删除与temp指向节点状态相同的节点Add_to_open(temp);sum_node++;}else;}else if(same=Search_A(open,temp)) //在open表中找到与新节点状态相同的节点{if(temp->f<same->f) //temp指向的节点,其代价比open表中相同状态节点代价小,加入open表{Remove_p(open,same); //从open表中删除与temp指向节点状态相同的节点Add_to_open(temp);sum_node++;}else ;}else //新节点为完全不同的新节点,加入open表{Add_to_open(temp);sum_node++;}}}//end右移if(n->i_0>=1) //空格所在列号不小于1,上移{temp=n->father;if(temp!=NULL&&temp->i_0==n->i_0-1&&temp->j_0==n->j_0) //新节点与其祖父节点相同;else //新节点与其祖父节点不同,或其父节点为起始节点{temp=(struct node *)malloc(sizeof(struct node)); //给新节点分配空间Copy_node(n,temp); //拷贝p指向的节点状态temp->s[temp->i_0][temp->j_0]=temp->s[temp->i_0-1][temp->j_0];//空格上移temp->s[temp->i_0-1][temp->j_0]=0;temp->i_0--;temp->d++;Calculate_f(temp->d,temp); //修改新节点的代价值temp->father=n; //新节点指向其父节点if(same=Search_A(closed,temp)) //在closed表中找到与新节点状态相同的节点{if(temp->f<same->f) //temp指向的节点,其代价比closed表中相同状态节点代价小,加入open表{Remove_p(closed,same); //从closed表中删除与temp指向节点状态相同的节点Add_to_open(temp);sum_node++;}else;}else if(same=Search_A(open,temp)) //在open表中找到与新节点状态相同的节点{if(temp->f<same->f) //temp指向的节点,其代价比open表中相同状态节点代价小,加入open表{Remove_p(open,same); //从open表中删除与temp指向节点状态相同的节点Add_to_open(temp);sum_node++;}else ;}else //新节点为完全不同的新节点,加入open表{Add_to_open(temp);sum_node++;}}}//end上移if(n->i_0<=1) //空格所在列号不大于1,下移{temp=n->father;if(temp!=NULL&&temp->i_0==n->i_0+1&&temp->j_0==n->j_0) //新节点与其祖父节点相同;else //新节点与其祖父节点不同,或其父节点为起始节点{temp=(struct node *)malloc(sizeof(struct node)); //给新节点分配空间Copy_node(n,temp); //拷贝p指向的节点状态temp->s[temp->i_0][temp->j_0]=temp->s[temp->i_0+1][temp->j_0]; //空格下移temp->s[temp->i_0+1][temp->j_0]=0;temp->i_0++;temp->d++;Calculate_f(temp->d,temp); //修改新节点的代价值temp->father=n; //新节点指向其父节点if(same=Search_A(closed,temp)) //在closed表中找到与新节点状态相同的节点{if(temp->f<same->f) //temp指向的节点,其代价比closed表中相同状态节点代价小,加入open表{Remove_p(closed,same); //从closed表中删除与temp指向节点状态相同的节点Add_to_open(temp);sum_node++;}else;}else if(same=Search_A(open,temp)) //在open表中找到与新节点状态相同的节点{if(temp->f<same->f) //temp指向的节点,其代价比open表中相同状态节点代价小,加入open表{Remove_p(open,same); //从open表中删除与temp指向节点状态相同的节点Add_to_open(temp);sum_node++;}else ;}else //新节点为完全不同的新节点,加入open表{Add_to_open(temp);sum_node++;}}}//end下移}if(bingo=1) Print_result(n); //输出解路径else printf("问题求解失败!");}//主函数结束//************************************************************************* //********************** ********************** //********************** 计算某个节点状态的代价值********************** //********************** ********************** //*************************************************************************void Calculate_f(int deepth,struct node *p){int i,j,temp;temp=0;for(i=0;i<=2;i++) //计算所有"不在位"数码的距离和{for(j=0;j<=2;j++){if((p->s[i][j])!=(s_g.s[i][j]))temp++;}}p->h=temp;p->f=deepth+p->h;}//*************************************************************************//********************** **********************//********************** 添加p指向的节点到open表中********************** //********************** **********************//*************************************************************************void Add_to_open(struct node *p){struct node *p1,*p2;p1=open; //初始时p1指向open表首部p2=NULL;if(open==NULL) //open表为空时,待插入节点即为open表第一个元素,open 指向该元素{p->next=NULL;open=p;}else //open表不为空时,添加待插入节点,并保证open表代价递增的排序{while(p1!=NULL&&p->f>p1->f){p2=p1; //p2始终指向p1指向的前一个元素p1=p1->next;}if(p2==NULL) //待插入节点为当前open表最小{p->next=open;open=p;}else if(p1==NULL) //待插入节点为当前open表最大{p->next=NULL;p2->next=p;}else //待插入节点介于p2、p1之间{p2->next=p;p->next=p1;}}}//***************************************************************************//********************** **********************//********************** 添加p指向的节点到closed表中**********************//********************** **********************//***************************************************************************void Add_to_closed(struct node *p){if(closed==NULL) //closed表为空时,p指向节点为closed表第一个元素,closed{p->next=NULL;closed=p;}else //closed表不为空时,直接放到closed表首部{p->next=closed;closed=p;}}//************************************************************************************* *************//********************************************//********************** 在open表或closed表中搜索和temp指向的节点相同的节点**********************//********************************************//*************************************************************************************struct node * Search_A(struct node *name,struct node *temp){struct node *p1;p1=name; //p1指向open表或closed表while(p1!=NULL){if(Test_A_B(p1,temp)) //找到相同的节点,返回该节点地址return p1;elsep1=p1->next;}return NULL;}//************************************************************************************* **********//********************************************//********************** 判断两个节点状态是否相同,相同则返回1,否则返回0 **********************//********************************************//************************************************************************************* **********int Test_A_B(struct node *p1,struct node *p2){int i,j,flag;flag=1;for(i=0;i<=2;i++)for(j=0;j<=2;j++){if((p2->s[i][j])!=(p1->s[i][j])) { flag=0; return flag; }else ;}return flag;}//******************************************************************************//********************** **********************//********************** 从open表或closed表删除指定节点********************** //********************** **********************//******************************************************************************void Remove_p(struct node *name,struct node *p){struct node *p1,*p2;p1=NULL;p2=NULL;if(name==NULL) //如果name指向的链表为空,则不需要进行删除return;else if(Test_A_B(name,p)&&name->f==p->f) //指定节点为name指向的链表的第一个元素{open=name->next;name->next=NULL;return;}else{p2=name;p1=p2->next;while(p1){if(Test_A_B(p1,p)&&p1->f==p->f) //找到指定节点{p2->next=p1->next;return;}else{p2=p1; //p2始终指向p1指向的前一个元素p1=p1->next;}}return;}}//************************************************************************************* *//********************************************//********************** 将p1指向的节点状态拷贝到p2指向的节点中**********************//********************************************//************************************************************************************* *void Copy_node(struct node *p1,struct node *p2){int i,j;for(i=0;i<=2;i++){for(j=0;j<=2;j++){ p2->s[i][j]=p1->s[i][j]; }}p2->i_0=p1->i_0;p2->j_0=p1->j_0;p2->f=p1->f;p2->d=p1->d;p2->h=p1->h;p2->next=p1->next;p2->father=p1->father;}//*********************************************************** //********************** ********************** //********************** 输出结果********************** //********************** ********************** //***********************************************************void Print_result(struct node *p){struct node *path[100];struct node *temp,*temp_father;int i,j,k;for(i=0;i<=99;i++) //初始化路径指针数组path[i]=0;temp=p;printf("总共扩展%d 个节点\n",sum_node);printf("总共扩展%d 层\n",temp->d);printf("解路径如下:\n");for(i=p->d;i>=0;i--) //存储解路径上各节点的地址{path[i]=temp;temp=temp->father;}for(k=0;k<=p->d;k++) //输出解路径{temp=path[k]; //建立节点指点指针printf("第%d步",temp->d);if(k-1>=0) //输出移动策略{temp_father=path[k-1];if(temp->i_0<temp_father->i_0) printf("->上移\n");if(temp->i_0>temp_father->i_0) printf("->下移\n");if(temp->j_0<temp_father->j_0) printf("->左移\n");if(temp->j_0>temp_father->j_0) printf("->右移\n");}elseprintf("\n");printf("当前节点状态为:\n");for(i=0;i<=2;i++){for(j=0;j<=2;j++){printf("%d ",temp->s[i][j]);}printf("\n");}printf("\n");}}THANKS !!!致力为企业和个人提供合同协议,策划案计划书,学习课件等等打造全网一站式需求欢迎您的下载,资料仅供参考。
智能控制(研究生)习题集
习题集第一章概论1.试从学科和能力两个方面说明什么是人工智能。
2.哪些思想、思潮、时间和人物在人工智能发展过程中起了重要作用?3.近年来人工智能研究取得哪些重要进展?4.为什么能够用计算机模拟人类智能?5.目前人工智能学界有哪些学派?它们的认知观为何?6.自动控制存在什么机遇与挑战?为什么要提出智能控制?7.简述智能控制的发展过程,并说明人工智能对自动控制的影响。
8.傅京孙对智能控制有哪些贡献?9.什么是智能控制?它具有哪些特点?10.智能控制器的一般结构和各部分的作用为何?它与传统控制器有何异同?11.智能控制学科有哪几种结构理论?这些理论的内容是什么?12.为什么要把信息论引入智能控制学科结构?13.人工智能不同学派的思想在智能控制上有何反映?第二章知识表示方法1.状态空间法、问题归约法、谓词逻辑法和语义网络法的要点是什么?它们有何本质上的联系及异同点?2.设有3个传教士和3个野人来到河边,打算乘一只船从右岸渡到左岸去。
该船的负载能力为两人。
在任何时候,如果野人人数超过传教士人数,那么野人就会把传教士吃掉。
他们怎样才能用这条船安全地把所有人都渡过河去?3.利用下图,用状态空间法规划一个最短的旅行路程:此旅程从城市A开始,访问其他城市不多于一次,并返回A。
选择一个状态表示,表示出所求得的状态空间的节点及弧线,标出适当的代价,并指明图中从起始节点到目标节点的最佳路径。
4.试说明怎样把一棵与或解树用来表达下图所示的电网络阻抗的计算。
单独的R、L或C可分别用R、jωL或1/jωC来计算,这个事实用作本原问题。
后继算符应以复合并联和串联阻抗的规则为基础。
5.试用四元数列结构表示四圆盘梵塔问题,并画出求解该问题的与或图。
6.用谓词演算公式表示下列英文句子(多用而不是省用不同谓词和项。
例如不要用单一的谓词字母来表示每个句子)。
A computer system is intelligent if it can perform a task which,if performed by a human, requires intelligence.7.把下列语句表示成语义网络描述:(1)All man are mortal.(2)Every cloud has a silver lining.(3)All branch managers of DEC participate in a profit-sharing plan.8.作为一个电影观众,请你编写一个去电影院看电影的剧本。
matlab习题及答案
matlab习题及答案Matlab习题及答案Matlab是一种强大的数学计算软件,被广泛应用于科学计算、数据分析和工程设计等领域。
在学习和使用Matlab的过程中,习题是一种非常有效的学习方式。
本文将给出一些常见的Matlab习题及其答案,帮助读者更好地掌握Matlab的使用技巧。
一、基础习题1. 计算1到100之间所有奇数的和。
解答:```matlabsum = 0;for i = 1:2:100sum = sum + i;enddisp(sum);```2. 编写一个函数,计算任意两个数的最大公约数。
解答:```matlabfunction gcd = computeGCD(a, b)while b ~= 0temp = b;a = temp;endgcd = a;end```3. 编写一个程序,生成一个5×5的随机矩阵,并计算矩阵的行和列的平均值。
解答:```matlabmatrix = rand(5);row_average = mean(matrix, 2);col_average = mean(matrix);disp(row_average);disp(col_average);```二、进阶习题1. 编写一个程序,实现插入排序算法。
解答:```matlabfunction sorted_array = insertionSort(array)n = length(array);for i = 2:nj = i - 1;while j > 0 && array(j) > keyarray(j+1) = array(j);j = j - 1;endarray(j+1) = key;endsorted_array = array;end```2. 编写一个程序,实现矩阵的转置。
解答:```matlabfunction transposed_matrix = transposeMatrix(matrix) [m, n] = size(matrix);transposed_matrix = zeros(n, m);for i = 1:mfor j = 1:ntransposed_matrix(j, i) = matrix(i, j);endendend```3. 编写一个程序,实现二分查找算法。
matlab习题答案
matlab习题答案MATLAB习题答案近年来,MATLAB(Matrix Laboratory)作为一种强大的数学软件工具,被广泛应用于科学计算、工程设计、数据分析等领域。
它提供了丰富的函数库和强大的计算能力,使得用户能够高效地解决各种数学问题。
然而,在学习和使用MATLAB的过程中,我们常常会遇到一些难题,需要寻找相应的解答。
本文将针对一些常见的MATLAB习题,提供一些解答和思路,以帮助读者更好地理解和应用MATLAB。
一、矩阵运算在MATLAB中,矩阵运算是一项重要的功能。
例如,给定一个矩阵A和一个向量b,我们需要求解线性方程组Ax=b。
可以使用MATLAB中的“\”运算符来实现,即x=A\b。
如果矩阵A是一个方阵且可逆,那么x将是方程组的唯一解。
如果A不可逆,那么x将是方程组的最小二乘解。
另外,MATLAB还提供了矩阵的转置、求逆、乘法等运算。
例如,可以使用“'”运算符来求矩阵的转置,即A'。
使用inv(A)函数可以求矩阵A的逆,使用A*B 可以实现矩阵的乘法。
二、数值积分数值积分是MATLAB中的另一个常见问题。
对于给定的函数f(x),我们需要计算其在某个区间[a, b]上的定积分。
可以使用MATLAB中的quad函数来实现数值积分,即quad(f, a, b)。
该函数会返回定积分的近似值。
如果需要进行多重积分,可以使用MATLAB中的dblquad函数或者triplequad 函数。
这些函数分别用于二重积分和三重积分的计算。
三、数据拟合在实际应用中,我们经常需要根据一组离散的数据点,拟合出一个函数。
MATLAB提供了polyfit函数来实现多项式拟合。
例如,对于给定的数据点x和y,可以使用p = polyfit(x, y, n)来拟合一个n次多项式。
返回的p是一个向量,包含了拟合多项式的系数。
除了多项式拟合,MATLAB还提供了其他拟合方法,如曲线拟合、指数拟合等。
八叉树算法 matlab代码
八叉树算法简介在计算机图形学和计算机视觉领域,八叉树算法是一种常用的数据结构,用于对三维空间进行分割和索引。
八叉树是一种树形结构,每个节点可以有最多8个子节点,因此得名为八叉树。
它的主要思想是将三维空间递归地划分为八个子立方体,从而实现对三维数据的快速检索和查询。
八叉树的构造八叉树的构造过程是通过递归实现的。
下面是八叉树的构造算法:1.初始化根节点,将整个空间作为根节点的区域。
2.对于每个节点,判断其区域中是否存在点或物体。
3.如果节点的区域中只有一个点或物体,则将该节点标记为叶子节点,并保存相应的点或物体信息。
4.如果节点的区域中有多个点或物体,则将该节点划分为八个子节点,每个子节点负责其父节点区域的1/8子区域。
5.对于每个子节点,重复步骤2-4,直到满足终止条件。
6.构造完整的八叉树后,可以根据需要进行查询和检索。
八叉树的应用八叉树算法在计算机图形学和计算机视觉领域有广泛的应用,以下是几个常见的应用场景:三维场景管理八叉树可以用于对三维场景进行管理和索引。
它可以将复杂的三维场景分割为多个子立方体,每个子立方体都有自己的节点,从而实现对场景中物体的高效检索和渲染。
点云数据处理八叉树也常用于处理点云数据。
点云是由大量点组成的三维数据集,通过八叉树可以对点云进行高效的存储和处理。
八叉树可以将点云数据划分为多个子区域,从而减少不必要的计算和存储开销。
基于体素的渲染八叉树在体素渲染中也有应用。
体素渲染是一种基于体素(三维像素)的渲染方法,八叉树可以对体素数据进行分割和索引,加速体素渲染的计算速度。
碰撞检测八叉树还可以用于碰撞检测。
在计算机游戏中,需要检测物体之间是否发生碰撞,八叉树可以将物体进行精确的划分,通过判断物体所在的子节点是否重叠,可以有效地进行碰撞检测。
八叉树的优缺点八叉树作为一种常用的数据结构,具有以下优点和缺点:优点•高效的数据检索和查询能力,可以减少不必要的计算和存储开销。
•可以对大规模的三维数据进行高效的管理和处理,提高计算效率。
matlab习题与答案
matlab习题与答案
MATLAB习题与答案
MATLAB是一种强大的数学软件,广泛应用于工程、科学和金融等领域。
通过MATLAB,用户可以进行数据分析、图像处理、模拟建模等多种操作。
为了帮
助大家更好地掌握MATLAB的应用,我们为大家准备了一些习题与答案,希望
能够帮助大家更好地理解和掌握MATLAB的使用。
习题一:编写一个MATLAB程序,实现对给定矩阵的转置操作。
解答:可以使用MATLAB中的transpose函数来实现矩阵的转置操作。
例如,
对于一个3x3的矩阵A,可以使用以下代码实现转置操作:
A = [1 2 3; 4 5 6; 7 8 9];
B = transpose(A);
习题二:编写一个MATLAB程序,实现对给定矩阵的逆矩阵计算。
解答:可以使用MATLAB中的inv函数来实现对矩阵的逆矩阵计算。
例如,对
于一个3x3的矩阵A,可以使用以下代码实现逆矩阵计算:
A = [1 2 3; 4 5 6; 7 8 9];
B = inv(A);
习题三:编写一个MATLAB程序,实现对给定矩阵的特征值和特征向量计算。
解答:可以使用MATLAB中的eig函数来实现对矩阵的特征值和特征向量计算。
例如,对于一个3x3的矩阵A,可以使用以下代码实现特征值和特征向量计算:A = [1 2 3; 4 5 6; 7 8 9];
[V, D] = eig(A);
通过以上习题与答案的学习,相信大家对MATLAB的应用已经有了更深入的了
解。
希望大家能够多加练习,不断提升自己的MATLAB技能,为今后的工作和学习打下坚实的基础。
洛谷P1379八数码难题(BFS)
洛⾕P1379⼋数码难题(BFS)题意:有⼀个3x3的的棋盘,有⼋个1~8的棋⼦,每次可以将⼀枚棋⼦移动到四周的空位,问最少移动多少次,使得最后的状态为123804765.题解:直接BFS,⽤map来Hash存步数,这⼉有个⽐较难想的点,就是把⼀维的坐标转化为⼆维的坐标(代码中有注释),然后我们找到0的位置,将四周可能的情况⼊队,不断下⼀层去找即可.代码:#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <stack>#include <queue>#include <vector>#include <map>#include <set>#include <unordered_set>#include <unordered_map>#define ll long long#define fi first#define se second#define pb push_back#define me memsetconst int N = 1e6 + 10;const int mod = 1e9 + 7;const int INF = 0x3f3f3f3f;using namespace std;typedef pair<int,int> PII;typedef pair<ll,ll> PLL;const int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};string s;int bfs(string s){string end="123804765";queue<string> q;unordered_map<string,int> dis;q.push(s);dis[s]=0;while(!q.empty()){auto tmp=q.front();q.pop();int d=dis[tmp];if(tmp==end) return d;int pos=tmp.find('0');int x=pos/3; // dim 2int y=pos%3;int y=pos%3;for(int i=0;i<4;++i){int a=x+dx[i];int b=y+dy[i];if(a>=0 && a<3 && b>=0 && b<3){swap(tmp[pos],tmp[a*3+b]); //dim 1 if(!dis.count(tmp)){dis[tmp]=d+1;q.push(tmp);}swap(tmp[pos],tmp[a*3+b]);}}}return -1;}int main() {ios::sync_with_stdio(false);cin.tie(0);cin>>s;cout<<bfs(s)<<endl;return 0;}。
八数码难题代码与基本思路 Eight puzzles
图搜索求解八数码算法--A*算法(步程差) 一.流程框图二.算法基本原理拓展节点并计算步程差,如果是目标节点,成功并退出,如果不是,判断是否为优质节点,是则拓展为子节点,否则舍弃;判断深度是否越界,是则失败,未越界则继续拓展节点,若拓展表为空,则失败退出。
八数码结构体由矩阵Array,步程差Value,屏蔽方向Undirect和父节点指针*parent四部分组成,Array存放矩阵数字状态,Value存放估值函数值,Undirect记录上一步移动方向避免逆推,*parent记录父子关系用于寻径。
三.模块分析Getgraph 键盘输入获得初始数码组并返回Graph结构体指针。
Printgraph 输入八数码结构体地址,打印矩阵数字状态与当前步程差。
Evaluate 输入目标矩阵与当前矩阵,计算步程差并返回值。
Move 输入当前矩阵与移动方向Direct,移动并返回新结构体地址。
Search 输入起始结构体与目标结构体,尝试寻径并记录路径并返回终点地址(若成功)或返回空指针(若失败)。
Main 主函数,定义目标矩阵并调用函数。
四.源代码// Eight-figure puzzle// A*#include"stdafx.h"#include<stdio.h>#include<stdlib.h>#define N 3 //数码组长度#define MAX 50 //最大搜索深度typedefstruct node//八数码结构体{int array[N][N];//数码组int Value;//评估值int Undirect;//所屏蔽方向,防止往回推到上已状态,1上2下3左4右struct node *parent;//父节点}Graph;Graph *Storage[MAX]; //拓展节点存储队列Graph *path[MAX]; //路径堆栈Graph *GetGraph(Graph *New_graph) ////////自定义初始数码组{int x;for (x = 0; x <N; x++){scanf("%d %d %d", &New_graph->array[x][0], &New_graph->array[x][1],&New_graph->array[x][2]);}New_graph->Value = 30;New_graph->Undirect = 0;New_graph->parent = NULL;return New_graph;}void PrintGraph(Graph *point_graph) /////////打印数码组{int i, j;if (point_graph == NULL)printf("NULL\n");else{printf(" ---------------\n");for (i = 0; i<N; i++){printf("| ");for (j = 0; j<N; j++){printf("%d ", point_graph->array[i][j]);}printf("|");if (i==N-1)printf(" Value %d ", point_graph->Value);//评估函数值printf("\n");}printf(" ---------------\n");}}int Evaluate(Graph *point_graph, Graph *End_graph) /////////评价函数{int value = 0;//评估值int i, j,m ,n ;for (i = 0; i<N; i++){for (j = 0; j<N; j++){for (m = 0; m <N; m++){for (n = 0; n <N; n++){if (point_graph->array[i][j] == End_graph->array[m][n])value = value + abs(i - m) + abs(j - n); //数字当前位置与目标位置步程差之和}}}}point_graph->Value = value;return value;}Graph *Move(Graph *point_graph, int Direct) /////////移动数码组{Graph *New_graph;int BlankLocate = 0;//定位空格指示int Movable = 1;//移动有效int i, j, x0, y0, x, y;for (i = 0; i<N; i++)//空格坐标i,j{for (j = 0; j<N; j++){if (point_graph->array[i][j] == 0){BlankLocate = 1;break;}}if (BlankLocate == 1)break;}x0 = i;y0 = j;switch (Direct){case 1://上x0--;if (x0<0)Movable = 0;break;case 2://下x0++;if (x0 >= N)Movable = 0;break;case 3://左y0--;if (y0<0)Movable = 0;break;case 4://右y0++;if (y0 >= N)Movable = 0;break;}if (Movable == 0)//不能移动则返回原节点return point_graph;New_graph = (Graph *)malloc(sizeof(Graph));//生成节点for (x = 0; x<N; x++){for (y = 0; y<N; y++){New_graph->array[x][y] = point_graph->array[x][y];//复制数码组}}New_graph->array[i][j] = New_graph->array[x0][y0];New_graph->array[x0][y0] = 0;return New_graph;}Graph *Search(Graph *Begin, Graph *End) /////////搜索函数{Graph *St1, *St2, *ta;int Step = 0;//深度int Direct = 0;//方向int i;int front, rear;front = rear = -1;//队列初始化ta = NULL;rear++;//入队Storage[rear] = Begin;while (rear != front)//队列不空{front++;//出队St1 = Storage[front];for (i = 1; i <= 4; i++)//分别从四个方向推导出新子节点{Direct = i;if (Direct == St1->Undirect)//跳过屏蔽方向continue;St2 = Move(St1, Direct);//移动数码组if (St2 != St1)//数码组是否可以移动{Evaluate(St2, End);//评价新的节点sif (St2->Value == 0)//为0则搜索完成{St2->parent = St1;rear++;Storage[rear] = St2;//存储节点到待处理队列ta = St2;break;}if (St2->Value <= St1->Value + 1){St2->parent = St1;//st2->Undirect=Direct>2?(Direct==3)+3:(Direct==1)+1;/屏蔽方向switch (Direct)//设置屏蔽方向,防止往回推{case 1://上St2->Undirect = 2;break;case 2://下St2->Undirect = 1;break;case 3://左St2->Undirect = 4;break;case 4://右St2->Undirect = 3;break;}rear++;Storage[rear] = St2;//存储节点到待处理队列}else{free(St2);//抛弃劣质节点St2 = NULL;}}}if (ta != NULL)//为0则搜索完成break;Step++;//统计深度if (Step>=MAX){break;}}return ta;}int main(int argc, constchar * argv[]){// 8 1 3 7 4 5 6 2 0// 4 1 3 2 7 5 8 0 6// 4 5 1 2 7 3 0 8 6 //16 steps in fact but failed//目标数码组Graph End_graph = {{{ 1, 2, 3 },{ 8, 0, 4 },{ 7, 6, 5 }}, 0, 0, NULL};//初始数码组Graph New_graph;Graph *Begin_graph;printf("Enter initial matrix line by line\n For example:\t1 3 4 ENTER\n\t\t8 2 5 ENTER\n\t\t7 6 0 ENTER\n\n");Begin_graph = GetGraph(&New_graph);Evaluate(Begin_graph, &End_graph);printf("Initial matrix:\n");PrintGraph(Begin_graph);printf("Target matrix:\n");PrintGraph(&End_graph);Graph *W, *P;int top = -1;//图搜索W = Search(Begin_graph, &End_graph);if (W){P = W; //压栈while (P != NULL){top++;path[top] = P;P = P->parent;}printf("<<<<<< The Path >>>>>>\n");//弹栈打印while (top>-1){P = path[top];top--;PrintGraph(P);}printf("<<<<< Mission Complete >>>>>\n");system("pause");}else{printf("Path not found ,Search depth is %d\n", MAX);system("pause");}return 0;}五.运行结果将初始数码组改写为 2 5 4 3 7 1 8 6 ,定义某个数前面比他小的数个数为Xi,所有数字的Xi相加为Y,因为四向移动只可能改变Y的大小,不改变其奇偶性。
matlab经典编程例题30道
MATLAB是一款功能强大的数学软件,其编程功能也受到越来越多人的关注。
下面介绍的是30个matlab经典编程例题,可以帮助大家熟悉matlab的编程语法,提高matlab 编程技能。
1. 请编写一个程序,计算出两个数的和。
2. 请编写一个程序,计算出两个数的最大值和最小值。
3. 请编写一个程序,计算出一组数据的平均值和标准差。
4. 请编写一个程序,将一个矩阵转置。
5. 请编写一个程序,求出两个矩阵的乘积。
6. 请编写一个程序,求出一个矩阵的逆矩阵。
7. 请编写一个程序,求出一个矩阵的行列式。
8. 请编写一个程序,计算出一元二次方程的解。
9. 请编写一个程序,计算出两个数组的相似度。
10. 请编写一个程序,计算出一个矩阵的特征值和特征向量。
11. 请编写一个程序,求出两个矩阵的秩。
12. 请编写一个程序,求出一个矩阵的特定元素。
13. 请编写一个程序,求出一组数据的最高值和最低值。
14. 请编写一个程序,求出两个数组的交集。
15. 请编写一个程序,求出一个矩阵的行和列之和。
16. 请编写一个程序,使用循环语句计算出100以内所有奇数的和。
17. 请编写一个程序,使用循环语句计算出1到1000以内的和。
18. 请编写一个程序,使用递归函数计算出斐波那契数列的第n项。
19. 请编写一个程序,求出一个多项式的导数。
20. 请编写一个程序,求出一个函数的极值点。
21. 请编写一个程序,求出一个数组的非零元素个数。
22. 请编写一个程序,计算出函数的不定积分。
23. 请编写一个程序,计算出函数的定积分。
24. 请编写一个程序,求出一个矩阵的秩。
25. 请编写一个程序,求出函数的极限值。
26. 请编写一个程序,求出一个矩阵的特征值分解。
27. 请编写一个程序,求出一个矩阵的LU分解。
28. 请编写一个程序,求出一个矩阵的QR分解。
29. 请编写一个程序,求出三次多项式的根。
30. 请编写一个程序,求出一个函数的积分。
matlab习题与答案
matlab习题与答案MATLAB习题与答案MATLAB是一种强大的数学软件,被广泛应用于科学、工程和金融等领域。
它不仅提供了丰富的数学函数和工具,还具备强大的数据可视化能力。
在学习和使用MATLAB的过程中,习题与答案的练习是非常重要的一部分。
本文将介绍一些常见的MATLAB习题,并给出相应的答案。
1. 习题:计算一个数组的平均值和标准差。
答案:```matlabA = [1, 2, 3, 4, 5];mean_A = mean(A);std_A = std(A);```2. 习题:生成一个10x10的随机矩阵,并计算其中每一行的和。
答案:```matlabA = rand(10, 10);row_sum = sum(A, 2);```3. 习题:计算两个数组的点积。
答案:```matlabA = [1, 2, 3];B = [4, 5, 6];dot_product = dot(A, B);```4. 习题:将一个字符串数组中的所有元素连接起来。
答案:```matlabstr_array = ["Hello", "World"];joined_str = strjoin(str_array);```5. 习题:计算一个数组中每个元素的平方根。
答案:```matlabA = [1, 4, 9, 16];sqrt_A = sqrt(A);```6. 习题:将一个数组中的所有负数替换为0。
答案:```matlabA = [-1, 2, -3, 4];A(A < 0) = 0;```7. 习题:计算一个矩阵的转置矩阵。
答案:```matlabA = [1, 2, 3; 4, 5, 6];transpose_A = A';```8. 习题:计算一个数组中的最大值和最小值。
答案:```matlabA = [1, 2, 3, 4, 5];max_A = max(A);min_A = min(A);```9. 习题:计算一个矩阵的行列式。
多种方法解决八数码难题
2 B C 2 8 3 h*=4,g*=1 2 8 3 1 4 W=3 1 6 4 P=4 7 6 5 f=5 7 5 E 3 2 3 1 8 4 7 6 5
h*=3,g*=2 W=3 P=3 f=5
W=5 P=6 f=7
F 2 8 3 1 4 7 6 5
W=4 P=5 f=7
G h*=2,g*=3
黑色数字表示不 在位的将牌数 A(6) 2 8 3 1 6 4 7 5 D(5) 2 8 3 3 1 4 7 6 5 G(6) 8 3 2 1 4 7 6 5 H(7) 2 8 3 7 1 4 6 5
S(4) 初始 2 8 3 1 1 6 4 7 5 B(4) 2 2 8 3 1 4 7 6 5 E(5) 2 1 8 7 6 I(5) 2 1 8 7 6 K(5) 1 2 8 7 6 4 C(6) 2 8 3 1 6 4 7 5 F(6) 2 8 3 1 4 7 6 5 J(7) 2 3 1 8 4 7 6 5
八数码难题
汇报时间:2018年10月 汇报人:马玥 PPT制作者:何帅帅 代码编辑调试者:尹迅、马玥
01 问题重述 Problem Retelling
目 录
CONTENTS
02 问题分析 Problem Analysis
03 宽度优先 Width First
04 深度优先 Depth First
05 启发式搜索
谢谢观赏
2 3 1 8 4 7 6 5 2 2 8 3 1 4 7 6 5 12 2 3 1 8 4 7 6 5
1
1 2 3 8 4 7 6 5 2 3 1 8 4 7 6 5 (目标状态)
6 2 8 3 1 4 7 6 5 8
9 2 8 3 1 4 7 6 5 10 2 8 1 4 3 7 6 5 2 8 1 4 3 7 6 5
matlab数学题
matlab数学题
当涉及到MATLAB数学题时,通常涉及到数值计算、符号计算、绘图、数据分析等方面。
MATLAB是一种强大的数学软件,可以用于解决各种数学问题。
首先,如果涉及到数值计算,MATLAB可以用于解线性方程组、求解微分方程、进行数值积分等。
对于线性方程组,可以使用MATLAB中的“\”操作符或者“inv”函数来求解。
对于微分方程,可以使用“ode45”等函数进行数值求解。
而对于数值积分,可以使用“quad”函数等来进行数值积分计算。
其次,如果涉及到符号计算,MATLAB中也提供了符号计算工具箱,可以进行符号计算,比如求解方程、化简表达式、求导、求积分等。
可以使用“solve”函数来求解方程,使用“simplify”函数来化简表达式,使用“diff”函数来求导,使用“int”函数来进行符号积分计算。
另外,MATLAB也非常擅长绘图,可以绘制各种类型的图形,包括二维图和三维图。
可以使用“plot”函数、“scatter”函数、“surf”函数等来进行绘图,还可以对图形进行装饰,添加标题、
坐标轴标签等。
此外,MATLAB还可以用于数据分析,可以进行数据的读取、处理、统计分析等。
可以使用“load”函数、“importdata”函数来读取数据,使用“mean”函数、“std”函数来进行统计分析,还可以进行数据可视化分析。
综上所述,MATLAB在数学问题的解决上具有很强的功能和灵活性,可以满足各种数学问题的求解和分析需求。
希望这些信息对你有所帮助。
八皇后问题matlab程序
function y=bahuanghou(); result=cell(1,8);N=100;for i=1:8result{i}={[1,i]};end;for i=1:8for j=2:8len=length(result{i});flagss=0;%看每一行运行的时候是不是第一次new_len=len;for m=1:lenaa=result{i};bb=aa{m};flags=0;%看第k行是否合适for k=1:8flags=0;if length(bb)<=j-2+eps%看找到的各行的点是否不合适了%,不合适就停止讨论continue;elsecc=zeros(j-1,1);cc=bb(1:j-1,2);for kk=1:length(cc(:,1))if find(cc(kk)==k) %如果发现在同一列上,跳出循环,继续下一列flags=1; break;end;if abs(k-cc(kk))==j-kk%如果在斜对角线上,跳出,继续下一列flags=1; break;end;end;if flagscontinue;end;if ~flagssaa{m}=[bb;j,k];%如果是第一次找到那一列,就直接在其末尾增加这个点result{i}=aa;flagss=flagss+1;elsenew_len=new_len+1;%如果不是第一次找到,就要新开辟一个集合aa{new_len}=[bb;j,k];result{i}=aa;end;end;end;end;end;end;% ret=zeros(8,N);ret=zeros(8,1);%寻找我已经找到的八皇后的结果for i=1:8aa=result{i};len=length(aa);for m=1:lenbb=aa{m};if length(aa{m})==8ret=[ret bb];end;end;end;%display(ret);%把八皇后的结果写入txt文档中进行结果保存fid=fopen('F:\ang.txt','w')for i=2:length(ret)fprintf(fid,'%d%d%d%d%d%d%d%d\r\n',ret(:,i)');if mod(i,2)fprintf(fid,'\r\n');end;end;size(ret)。
八数码难题代码
八数码难题代码这是一个练习BFS的好东西,很经典。
我只是来帖我的代码的,代码加调试一共50多分钟,我还是很弱啊...typearr= array[1..3,1..3]of integer;varSource,Target :arr;q :array[1..1000000]of arr;jiecheng :array[1..10]of longint;deep :array[1..1000000]of longint;hash :array[1..1000000]of boolean;Procedure init;beginassign(input,'input.txt');reset(input);assign(output,'output.txt');rewrite(output);end;Procedure terminate;beginclose(input);close(output);halt;end;Procedure calcjiecheng;vari:longint;beginjiecheng[1]:=1;for i:=2 to 10 dojiecheng[i]:=jiecheng[i-1]*i;end;Function cantor(s:arr):longint;//康托展开,用于哈希。
vari,j,temp:integer;ss:array[1..9]of longint;num,sum:longint;beginsum:=1;for i:=1 to 3 do for j:=1 to 3 dobeginss[sum]:=s[i,j];inc(sum);end;num:=0;for i:=1 to 8 dobegintemp:=0;for j:=i+1 to 9 doif ss[j]<ss[i] then inc(temp);num:=num+jiecheng[9-i]*temp;end;exit(num+1);end;Procedure writeans(x:longint);beginwriteln(x);terminate;end;Function Move(a:arr;var b:arr;x:longint):boolean;//指的是将X状态按照第i个方案移动到Y状态。
人工智能实验一_八数码问题
用A*算法解决八数码问题1 问题描述1.1 待解决问题的解释八数码游戏(八数码问题)描述为:在3×3组成的九宫格棋盘上,摆有八个将牌,每一个将牌都刻有1-8八个数码中的某一个数码。
棋盘中留有一个空格,允许其周围的某一个将牌向空格移动,这样通过移动将牌就可以不断改变将牌的布局。
这种游戏求解的问题是:给定一种初始的将牌布局或结构(称初始状态)和一个目标的布局(称目标状态),问如何移动将牌,实现从初始状态到目标状态的转变。
1.2 问题的搜索形式描述(4要素)初始状态:8个数字将牌和空格在九宫格棋盘上的所有格局组成了问题的状态空间。
其中,状态空间中的任一种状态都可以作为初始状态。
后继函数:通过移动空格(上、下、左、右)和周围的任一棋子一次,到达新的合法状态。
目标测试:比较当前状态和目标状态的格局是否一致。
路径消耗:每一步的耗散值为1,因此整个路径的耗散值是从起始状态到目标状态的棋子移动的总步数。
1.3 解决方案介绍(原理)对于八数码问题的解决,首先要考虑是否有答案。
每一个状态可认为是一个1×9的矩阵,问题即通过矩阵的变换,是否可以变换为目标状态对应的矩阵?由数学知识可知,可计算这两个有序数列的逆序值,如果两者都是偶数或奇数,则可通过变换到达,否则,这两个状态不可达。
这样,就可以在具体解决问题之前判断出问题是否可解,从而可以避免不必要的搜索。
如果初始状态可以到达目标状态,那么采取什么样的方法呢?常用的状态空间搜索有深度优先和广度优先。
广度优先是从初始状态一层一层向下找,直到找到目标为止。
深度优先是按照一定的顺序前查找完一个分支,再查找另一个分支,以至找到目标为止。
广度和深度优先搜索有一个很大的缺陷就是他们都是在一个给定的状态空间中穷举。
这在状态空间不大的情况下是很合适的算法,可是当状态空间十分大,且不预测的情况下就不可取了。
他的效率实在太低,甚至不可完成。
由于八数码问题状态空间共有9!个状态,对于八数码问题如果选定了初始状态和目标状态,有9!/2个状态要搜索,考虑到时间和空间的限制,在这里采用A*算法作为搜索策略。
人工智能 八数码难题
实验报告课程名称人工智能_____________实验项目八数码难题______________实验仪器电脑、visual C++_________系别____________ 专业__ _____班级/学号学生姓名_ _________实验日期____成绩_______________________指导教师_________一、实验目的理解并熟悉掌握深度优先搜索和广度优先搜索地方法。
二、实验内容九宫格中有8个数码,其中只有一个空,规则是只能把一个数码移动到空的格子中,要求从一个初始状态移动到一个目标状态所要花费的最少步数【算法分析】解决此类问题的办法是宽度搜索,深度搜索耗时太大无法接受。
当需要移动的步数很多时,普通的宽度搜索仍旧无法满足需要,需要对其进行优化。
这个问题也可以推广到流行的拼图游戏。
【具体步骤】一、确定问题规模(考虑搜索的时间代价)二、确定产生式规则(如果规则太多,则时间代价会很大)三、套用经典宽度搜索框架写程序三、代码和结果#include <stdlib.h>#include <stdio.h>typedef struct Node {int num[9]; //棋盘状态int deepth; //派生的深度g(n)int diffnum; //不在位的数目h(n)int value; //耗散值f(n)=g(n)+h(n)struct Node * pre;struct Node * next;struct Node * parent;}numNode; /* ---------- end of struct numNode ---------- */int origin[9]; //棋盘初始状态int target[9]; //棋盘目标状态int numNode_num,total_step;numNode *open,*close; //Open表和Close表numNode *create_numNode(){return (numNode *)malloc(sizeof(numNode));}numNode *open_getfirst(numNode *head); //返回第一项,并从Open表中删除void open_insert(numNode *head,numNode *item); //向Open表中按序插入新节点void close_append(numNode *head,numNode *item); //向Close表中插入新节点int expand(numNode *item); //扩展节点int print_result(numNode *item); //打印结果numNode *copy_numNode(numNode *orgin);char isNewNode(numNode *open,numNode *close,int num[9]);//是否在Open表或Close表中void print_num(int num[9]); //打印棋盘状态int diff(int num[9]); //求不在位棋子的个数void init(); //初始化,获得棋盘初始状态和目标状态void swap(int *a,int *b);int operate(int num[],int op);void free_list(numNode *head);/** === FUNCTION ======================================================================* Name: 主函數* Description: 程序入口*=============================================================================== ======*/intmain ( int argc, char *argv[] ){//初始化Open表和Close表open=create_numNode();close=create_numNode();open->pre=open->next=close->pre=close->next=NULL;init(); //由用户输入初始和目标状态//初始化初始节点numNode *p1;p1=create_numNode();p1->parent=NULL;p1->deepth=0;int i=0;for ( i=0; i<9; i++){p1->num[i]=origin[i];}open_insert(open,p1);numNode_num=1;p1=open_getfirst(open);while (p1!=NULL){close_append(close,p1);if(expand(p1))return EXIT_SUCCESS;p1=open_getfirst(open);}printf("No solution!\n");return EXIT_SUCCESS;} /* ---------- end of function main ---------- */voidinit ( ){while(1){printf("Please input opriginal status:\nFor example:123456780 stands for\n""1 2 3\n""4 5 6\n""7 8 0\n");char temp[10];scanf("%s",&temp);int i=0;for ( i=0;i<9 && temp[i]-'0'>=0 && temp[i]-'0'<=8; i++) {origin[i]=temp[i]-'0';}printf("Please input target status:\n");scanf("%s",&temp);int j=0;for ( j=0; j<9 && temp[j]-'0'>=0 && temp[j]-'0'<=8; j++){target[j]=temp[j]-'0';}system("cls");if ( i==9&&j==9){break;}}} /* ----- end of function init ----- */voidopen_insert (numNode *head,numNode *item){numNode *p,*q;p=head->next;q=head;while ( p!=NULL && item->value > p->value ){q=p;p=p->next;}q->next=item;item->pre=q;item->next=p;if(p!=NULL){p->pre=item;}} /* ----- end of function open_insert ----- */numNode *open_getfirst (numNode *head){numNode *p;if ( head->next == NULL ){return NULL;}p=head->next;head->next=p->next;if ( p->next != NULL ){p->next->pre=head;}p->pre=NULL;p->next=NULL;return p;} /* ----- end of function open_getfirst ----- */voidclose_append (numNode *head,numNode *item) {item->next=head->next;item->pre=head;head->next=item;if ( item->next!=NULL ){item->next->pre=item;}} /* ----- end of function close_append ----- */intexpand (numNode *p1){numNode * p2;int op=1;for ( op=1; op<=4; op++){p2=copy_numNode(p1);operate(p2->num,op);if(isNewNode(open,close,p2->num)=='N'){p2->parent=p1;p2->deepth=p1->deepth+1;p2->diffnum=diff(p2->num);p2->value=p2->deepth+p2->diffnum;if(p2->diffnum==0){total_step=print_result(p2);printf("Total step: %d\n",total_step);free_list(open);free_list(close);return 1;}else{numNode_num++;open_insert(open,p2);}}elsefree(p2);}return 0;} /* ----- end of function expand ----- */intoperate(int m[], int op){int blank;blank=0;while (m[blank]!=0 && blank<9 )++blank;if (blank==9)return 1;switch (op) {case 1: /* up */if (blank>2)swap(m+blank,m+blank-3);break;case 2: /* down */if (blank<6)swap(m+blank,m+blank+3);break;case 3: /* left */if (blank!=0 && blank!=3 && blank!=6)swap(m+blank,m+blank-1);break;case 4: /* right */if (blank!=2 && blank!=5 && blank!=8)swap(m+blank,m+blank+1);break;default : return 1;}return 0;}voidswap(int *a, int *b){int c;c=*a;*a=*b;*b=c;}numNode *copy_numNode (numNode *origin){numNode *p;p=create_numNode();p->deepth=origin->deepth;p->diffnum=origin->diffnum;p->value=origin->value;int i;for ( i=0; i<9; i++){(p->num)[i]=(origin->num)[i];}return p;} /* ----- end of function copy_numNode ----- */intdiff (int num[9]){int i,diffnum=0;for(i=0;i<9;i++)if(num[i]!=target[i])diffnum++;return diffnum;} /* ----- end of function diff ----- */charisNewNode (numNode *open,numNode *close,int num[9]) {numNode *p;int i=0;p=open->next;while ( p!=NULL ){for ( i=0; i<9; i++){if(p->num[i]!=num[i])break;}if(i==9)return 'O'; //Openp=p->next;}p=close->next;while ( p!=NULL ){for ( i=0; i<9; i++){if(p->num[i]!=num[i])break;}if(i==9)return 'C'; //Closep=p->next;}return 'N';} /* ----- end of function isNewNode ----- */voidfree_list (numNode *head){numNode *p,*q;p=head->next;while ( p!=NULL ){q=p->next;free(p);p=q;}free(head);} /* ----- end of function free_list ----- */voidprint_num (int num[9]){int i;for ( i=0; i<9; i++){printf("%d\t",num[i]);if((i%3)==2)printf("\n");}} /* ----- end of function print_num ----- */intprint_result ( numNode *item){numNode *p;int step;p=item;if(p!=NULL){step=print_result(p->parent);printf("\nStep %d:\n",step+1);print_num(p->num);return step+1;}else{return -1;}}四.实验心得这次试验让我更加深入了解了什么是人工智能,让我了解了人工智能的作用以及含义和人工智能的使用范围以及对于我们未来生活得作用的广大。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、实验目的1、熟悉和掌握启发式搜索的定义、估价函数和算法过程。
2、利用A*算法求解N数码难题,理解求解流程和搜索顺序。
二、实验内容以八数码为例实现A或A*算法。
1、分析算法中的OPEN表CLOSE表的生成过程。
1)建立一个队列,计算初始结点的估价函数f,并将初始结点入队,设置队列头和尾指针。
2)取出队列头(队列头指针所指)的结点,如果该结点是目标结点,则输出路径,程序结束。
否则对结点进行扩展。
3)检查扩展出的新结点是否与队列中的结点重复,若与不能再扩展的结点重复(位于队列头指针之前),则将它抛弃;若新结点与待扩展的结点重复(位于队列头指针之后),则比较两个结点的估价函数中g的大小,保留较小g值的结点。
跳至第五步。
4)如果扩展出的新结点与队列中的结点不重复,则按照它的估价函数f大小将它插入队列中的头结点后待扩展结点的适当位置,使它们按从小到大的顺序排列,最后更新队列尾指针。
5)如果队列头的结点还可以扩展,直接返回第二步。
否则将队列头指针指向下一结点,再返回第二步。
2、分析估价函数对搜索算法的影响。
3、分析启发式搜索算法的特点。
广度优先搜索和双向广度优先搜索都属于盲目搜索,这在状态空间不大的情况下是很合适的算法,可是当状态空间十分庞大时,它们的效率实在太低,往往都是在搜索了大量无关的状态结点后才碰到解答,甚至更本不能碰到解答。
搜索是一种试探性的查寻过程,为了减少搜索的盲目性引,增加试探的准确性,就要采用启发式搜索了。
所谓启发式搜索就是在搜索中要对每一个搜索的位置进行评估,从中选择最好、可能容易到达目标的位置,再从这个位置向前进行搜索,这样就可以在搜索中省略大量无关的结点,提高了效率。
启发式函数选取为:f*(n)=g*(n)+ h*(n)其中:g*(n)是搜索树中节点n的深度h*(n)用来计算对应于节点n的数据中错放的棋子个数。
三、实验结果四、程序function [a1,b1]=shang(a)[x,y]=find(a==0);a1=a;a1(x,y)=a(x-1,y);a1(x-1,y)=0;b1=zhao(a1); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [a1,b1]=xia(a)[x,y]=find(a==0);a1=a;a1(x,y)=a(x+1,y);a1(x+1,y)=0;b1=zhao(a1); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [a1,b1]=zuo(a)[x,y]=find(a==0);a1=a;a1(x,y)=a(x,y-1);a1(x,y-1)=0;b1=zhao(a1); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [a1,b1]=you(a)[x,y]=find(a==0);a1=a;a1(x,y)=a(x,y+1);a1(x,y+1)=0;b1=zhao(a1); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function z=panduan(a)global E;global I;I=2;[x,y]=size(E);z=1;for i=1:yb=E{i};v=(b-a).^2;if sum(sum(v))==0z=0;break;endend %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function y=zhao(a)wan=[1 2 3;8 0 4;7 6 5];y=0;b=a-wan;for i=1:3for j=1:3if b(i,j)~=0y=y+1;endendend %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% global Eglobal Ia=[2 8 3;1 0 4;7 6 5];b=[1 2 3;8 0 4;7 6 5];I=1;E(1)={a};for i=2:20q=b-E{i};if sum(sum(q.^2))E(i)={kaka(E{i-1})};celldisp(E(i))elsebreak;endend %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [a1]=kaka(a)global I;global E;c=[2 8 3;1 0 4;7 6 5];E(1)={c};[x,y]=find(a==0);z=9;if x==1if y==1[x1,y1]=xia(a);if y1<zif panduan(x1)b=x1;z=y1;endend[x2,y2]=you(a);if y2<zif panduan(x2)b=x2;z=y2;endenda1=b;endif y==2[x1,y1]=xia(a);if y1<zif panduan(x1)b=x1;z=y1;endend[x2,y2]=zuo(a);if y2<zif panduan(x2) b=x2;z=y2;endend[x3,y3]=you(a);if y3<zif panduan(x3) b=x3;z=y3;endenda1=b;endif y==3[x1,y1]=xia(a);if y1<zif panduan(x1) b=x1;z=y1;endend[x2,y2]=zuo(a);if y2<zif panduan(x2) b=x2;z=y2;endenda1=b;endendif x==2if y==1[x1,y1]=shang(a);if y1<zif panduan(x1) b=x1;z=y1;endend[x2,y2]=xia(a);if y2<zif panduan(x2)b=x2;z=y2;endend[x3,y3]=you(a);if y3<zif panduan(x3) b=x3;z=y3;endenda1=b;endif y==2[x1,y1]=shang(a);if y1<zif panduan(x1); b=x1;z=y1;endend[x2,y2]=xia(a);if y2<zif panduan(x2); b=x2;z=y2;endend[x3,y3]=zuo(a);if y3<zif panduan(x3); b=x3;z=y3;endend[x4,y4]=you(a);if y4<z;if panduan(x4) b=x4;z=y4;endenda1=b;endif y==3[x1,y1]=shang(a);if y1<zif panduan(x1) b=x1;z=y1;endend[x2,y2]=xia(a);if y2<zif panduan(x2) b=x2;z=y2;endend[x3,y3]=zuo(a);if y3<zif panduan(x3) b=x3;z=y3;endenda1=b;endendif x==3if y==1[x1,y1]=shang(a);if y1<zif panduan(x1) b=x1;z=y1;endend[x4,y4]=you(a);if y4<z;if panduan(x4) b=x4;z=y4;endenda1=b;endif y==2[x1,y1]=shang(a);if y1<zif panduan(x1)b=x1;z=y1;endend[x3,y3]=zuo(a);if y3<zif panduan(x3)b=x3;z=y3;endend[x4,y4]=you(a);if y4<z;if panduan(x4)b=x4;z=y4;endenda1=b;endif y==3[x1,y1]=shang(a);if y1<zif panduan(x1)b=x1;z=y1;endend[x3,y3]=zuo(a);if y3<zif panduan(x3)b=x3;z=y3;endenda1=b;endendE(I)={a1};五、实验结论1、启发式搜索算法A*流程图和算法框图。
算法框图:算法方法:利用MATLAB软件,因为MATLAB是基于矩阵运算的,八数码可以看做是一个3*3的矩阵,将八数码中的空位可看成矩阵的为0代替,已进行矩阵之间的运算,首先建立了4个函数,这4个函数应有在矩阵的上,下,左,右的变换,然后经过变换,输出两个值,一个为变换后的矩阵,一个为变化后的放错位置的数值,然后利用kaka函数,分别分9中情况来条用这4个函数,来输出下一层的矩阵并判断最小放错位置的数值,然后将其矩阵放入全局变量E中的元胞数组中,记录下其实的矩阵,然后再每次生成下一层矩阵时,利用panduan函数来判断生成的矩阵是否和E元胞数组中的矩阵相同,防止出现矩阵变化中的内部死循环。
然后利用celldisp函数输出E元胞数组中的矩阵,即为起始棋局到目标棋局的路径。
2、分析估价函数的值对搜索算法速度的影响。
考虑到八数码问题的特点,在本实验中使用A*算法求解。
A*搜索是一种效的搜索算法,它把到达节点的耗散g(n)和从该节点到目标节点的消耗h(n)结合起来对节点进行评价:f(n)=g(n)+h(n)。
当h(n)是可采纳时,使用Tree-Search的A*算法将是最优的。
3、根据A*算法分析启发式搜索的特点。
启发式搜索是一种试探性的查寻过程,为了减少搜索的盲目性引,增加试探的准确性,就要采用启发式搜索了。
所谓启发式搜索就是在搜索中要对每一个搜索的位置进行评估,从中选择最好、可能容易到达目标的位置,再从这个位置向前进行搜索,这样就可以在搜索中省略大量无关的结点,提高了效率。