人工智能实验报告 AI1_c_PB10210159

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


自动化 系 10 级


姓名

王云龙
评分:
学号 PB10210159
日期 2013-04-29
return i; } 安全性要求检测函数 jiancha(),确定两岸的修道士是否安全 int jiancha(DataType x,int n) // 安全性检测,检查当前情况下,修道士是否 安全 { if ((x.xds>=x.yr||x.xds==0)&&((n-x.xds)>=(n-x.yr)||x.xds==n)&&x.xds>=0&&x.xds<=n &&x.yr>=0&&x.yr<=n) //当初始岸上修道士的人数大于野人人数,或修道士人数为 0;或目的岸 上修道士人数为 n,且修道士人数满足 0~n,野人人数也是如此(无负数情形) return 1;//满足要求返回 1; else return 0;//不满足要求返回 0 } 结果显示函数 print() void print(Slink *q,Slink *p) //, 在屏幕上显示结果;打印安全渡河的过程 { DataType a[100]; int i=1; a[0].bs=0; a[0].xds=0; a[0].yr=0; //设置一个目标节点,即(0,0,0)初始岸上已无人,且船在 目的岸上; while (q!=p) { a[i]=q->data; q=q->par; i++; } while ((--i)>=0) { printf("( %d %d %d )",a[i].xds,a[i].yr,a[i].bs); if (!(a[i].xds==0&&a[i].yr==0&&a[i].bs==0)) { if (a[i].bs==1) // 船在初始岸上的输出情况 printf(" --> ( %d %d ) --> ( %d %d 0 )\n",a[i].xds-a[i-1].xds,a[i].yr-a[i-1].yr,a[i-1].xds,a[i-1].yr); else printf(" <-( %d %d ) <-( %d %d 1 )\n",(a[i].xds-a[i-1].xds)*(-1),(-1)*(a[i].yr-a[i-1].yr),a[i-1].xds,a[i-1].yr); }//船在目的岸上的输出情况 else printf("\n"); }
操作的定义与表示 渡河问题中的操作算子可以定义 2 类:L(m,c)、R(m,c),分别指示从左岸到右岸的划 船操作和从右岸回到左岸的划船操作。由于 m 和 c 取值的可能组合只有 5 个:10, 20,11,01,02,故而总共有 10 个操作算子: F={L01,L10,L11, L02,L20,R01, R10, R11,R02, R20}。 问题的求解 在状态空间中, 寻找出从初始状态<3,3,0>出发,到达目标状态<0,0,1>的路径,寻找操 作序列,本质上从初始状态到目标状态的路径。

自动化 系 10 级


姓名

王云龙
评分:
学号 PB10210159
日期 2013-04-29
另外,某些合法状态不可达,例如状态(0,0,1) , (0,3,0) 。 因此,这个问题总共只有 16 个可达的合法状态。全部状态如下:
表1 状 态 S0 S1 S2 S3 S4 S5 S6 S7 m, c, b 3,3,1 3,2,1 3,1,1 3,0,1 2,3,1 2,2,1 2,1,1 2,0,1 M-C 问题的全部可能状态 (红色标注为合法且可达状态 ) 状 态 S8 S9 S10 S11 S12 S13 S14 S15 m, c, b 1,3,1 1,2,1 1,1,1 1,0,1 0,3,1 0,2,1 0,1,1 0,0,1 状 态 S16 S17 S18 S19 S20 S21 S22 S23 m, c, b 3,3,0 3,2,0 3,1,0 3,0,0 2,3,0 2,2,0 2,1,0 2,0,0 状 态 S24 S25 S26 S27 S28 S29 S30 S31 m, c, b 1,3,0 1,2,0 1,1,0 1,0,0 0,3,0 0,2,0 0,1,0 0,0,0
知识准备:
(一 ) 状态空间表示法:一种基于图的表示方法,即表示该问题的全部可能的状 态及其相互关系构成的图。表示为:<Qs,F,Qg> ,Qs 为初始状态的集合 ); F 为操作的集合;Qg 为目标状态的集合。 (二 ) 状态空间的一般搜索过程:首先把问题的初始状态( 即初始节点) 作为当前 状态,选择适用的算符对其进行操作,生成一组子状态,然后检查目标状 态是否在其中出现。若出现,则搜索成功;若不成功,则按某种搜索策略 从已生成的状态中再选一个状态作为当前状态。重复以上过程,知道目标 状态出现货不再有可供操作的状态及算符时为止。搜索策略主要有两种: 启发式搜索和盲目搜索。 (三 ) 启发式搜索:在搜索的过程中,应用问题解的有关的知识,动态地确定操 作规则,优先地扩展最有希望的节点,使搜索更快地朝着目标前进,从而 扩展的节点少,效率高。

自动化 系 10 级


姓名

王云龙
评分:
学号 PB10210159
日期 2013-04-29
printf("渡河成功!\n"); } 程序的核心函数 solve() void solve(Slink *p,int n,int c) { Slink *q,*t; DataType tem; int i,flag,flag1,g=0,j,count=0; q=p->son; while (q!=NULL) { flag=0; j=findfa(q->data,c); for (i=0;i<j;i++) { tem.xds=q->data.xds-fa[i].xds; tem.yr=q->data.yr-fa[i].yr; tem.bs=1-q->data.bs; t=q; if (jiancha (tem,n)) { flag1=1; while (t!=p) // 非重复节点,避免死循环; { if(tem.xds==t->data.xds&&tem.yr==t->data.yr&&tem.bs==t->data.bs) { flag1=0; break; } t=t->par; } if(flag1==1) { if (flag==0) { insertson(q, tem); flag=1; } else insertbro(q,tem); if (tem.xds==0&&tem.yr==0&&tem.bs==0) { print(q,p); count++;
程序设计 :
A. 状态空间盲目搜索的程序设计
i. { int xds; //修道士的人数; int yr; //野人的人数; int bs; //boat side 船的位置(左岸或右岸) ;bs=1 在起始岸上;bs=0 在目的 岸上 }DataType;//状态表示的数据部分结构体定义; ii. 状态空间(状态之间关系)表示——树或邻接表的建立 typedef struct node // 状态表示出数据部分外,构造解树所需的指针节点; { DataType data; //状态表示中数据部分; struct node *son; // 子节点指针; struct node *bro; // 兄弟节点; struct node *par; // 父节点; struct node *next; // 下一个节点; 状态的表示数据结构: typedef struct

自动化 系 10 级


姓名

王云龙
评分:
学号 PB10210159
日期 2013-04-29
生成所有满足运送要求的船上传道士和野人的情况 findfa() int findfa(DataType x,int c) // 生成在船上修道士仍安全的几种情况;其中 n 为船能容纳的人数; //即在船上的时候修道士的人数也要比野人的数量要多(除非修道士人数为 0) { int i=0,a,b,t=0; if(x.bs)//船在初始岸上时,所有可能的船上人的情况,未考虑合法和要求, 只是数学上的排列组合; { a=0;b=c-a; while (a+b>=1) { t++;//t 为逐渐减少的船上的人数,直到只有 1 人; while (b>=0) { fa[i].xds=a; fa[i].yr=b; i++; a++; b--; } a=0; b=c-a-t; } } else //船在目的岸上的情况,与在初始岸上的情况类似,只是因以目的岸 上的人数为准,船回去时的人数使目的岸上人数减少 { a=1;b=0;t=0; while (a+b<=c) { t++; while (a>=0) { fa[i].xds=a*(-1); fa[i].yr=b*(-1); i++; a--; b++; } a=fa[0].xds*(-1)+t; b=0; } }

自动化 系 10 级


姓名

王云龙
评分:
学号 PB10210159
日期 2013-04-29
实验题目:状态空间启发式搜索(修道士与野人问题) 实验目的:理解启发式搜索的概念,掌握状态空间搜索技术;使用线程解
决 M-C(The Missionaries and Cannibals Problem)问题。
问题分析:
人物: 3 个修道士和 3 个野人 道具:一条最多只能坐 2 个人的小船 约束:任何时候在河的两岸上,修道士的人数不能少于野人的个数 目标:成功地从河的左岸到达河的右岸的方案 图示如下,其中“△”表示修道士, “×”表示野人, “ ” 表示小船。

经过对问题的分析,我们可以用状态空间表示法对问题进行表示与求解: 状态的表示:<m,c,b> 其中 m 为左岸修道士的个数 c 为左岸野人的个数 b 为右岸船的个数(左:0;右 1)
初始状态:<3,3,0> 目标状态:<0,0,1> 状态空间的特性: 在这个问题中,状态空间可能的状态总数为 4×4×2 = 32 ,但由于要遵守安全约束, 只有 20 个状态是合法的,如(1,3,1) , (2,3,1) 。 下面是几个不合法状态的例子: (1,0,1) , (1,2,1) , (2,3,1)

自动化 系 10 级


姓名

王云龙
评分:
学号 PB10210159
日期 2013-04Fra Baidu bibliotek29
iii.
}Slink; 初始化解树函数 init() void init(Slink **head) // 初始化解树根节点的函数; { *head=(Slink *)malloc(sizeof(Slink)); //动态分配空间 (*head)->son=NULL; (*head)->bro=NULL; (*head)->par=NULL; (*head)->next=NULL; } 插入子节点的函数 insertson() void insertson(Slink *head, DataType x) // 插入子结点的操作函数; { Slink *q,*s; q=(Slink *)malloc(sizeof(Slink));// 动态分配空间,建立一个节点; q->data=x; head->son=q; s=head; while (s->next!=NULL) s=s->next; q->par=head; q->son=NULL; q->bro=NULL; s->next=q; q->next=NULL; } 插入兄弟节点的函数 insertbro() void insertbro(Slink *head,DataType x) // 在邻接表中插入兄弟结点的操作, 所有的兄弟结点都指向他们右边的结点; { Slink *q,*s; q=(Slink *)malloc(sizeof(Slink)); s=head->son; q->data=x; while (s->bro!=NULL) s=s->bro; s->bro=q; s->next=q; q->next=NULL; q->bro=NULL; q->par=head; q->son=NULL; }
相关文档
最新文档