实验一 知识表示方法Word文档格式.docx
- 文档编号:18157592
- 上传时间:2022-12-13
- 格式:DOCX
- 页数:16
- 大小:21.63KB
实验一 知识表示方法Word文档格式.docx
《实验一 知识表示方法Word文档格式.docx》由会员分享,可在线阅读,更多相关《实验一 知识表示方法Word文档格式.docx(16页珍藏版)》请在冰豆网上搜索。
OptimalProcedure:
221->
四、实验组织运行要求
本实验采用集中授课形式,每个同学独立完成上述实验要求。
五、实验条件
每人一台计算机独立完成实验。
#include<
stdio.h>
malloc.h>
stdlib.h>
typedefstruct
{
intxds;
//xiudaoshi
intyr;
//yeren
intcw;
//chuanwei
}DataType;
DataTypefa[50000];
typedefstructnode
DataTypedata;
structnode*son;
structnode*bro;
structnode*par;
structnode*next;
}Ltable;
voidLtableinit(Ltable**head)//初始化邻接表的操作
*head=(Ltable*)malloc(sizeof(Ltable));
//动态分配空间
(*head)->
son=NULL;
bro=NULL;
par=NULL;
next=NULL;
}
voidinsertson(Ltable*head,DataTypex)//在邻接表中插入儿子结点的操作
Ltable*q,*s;
q=(Ltable*)malloc(sizeof(Ltable));
q->
data=x;
head->
son=q;
s=head;
while(s->
next!
=NULL)
s=s->
next;
par=head;
s->
next=q;
voidinsertbro(Ltable*head,DataTypex)//在邻接表中插入兄弟结点的操作,所有的兄弟结点都指向他们右边的结点;
s=head->
son;
bro!
bro;
bro=q;
intfindfa(DataTypex,intn)//生成在船上修道士仍安全的几种情况;
inti=0,a,b,t=0;
if(x.cw)
{
a=0;
b=n-a;
while(a+b>
=1)
t++;
while(b>
=0)
fa[i].xds=a;
fa[i].yr=b;
i++;
a++;
b--;
}
b=n-a-t;
else
a=1;
b=0;
t=0;
while(a+b<
=n)
while(a>
{
fa[i].xds=a*(-1);
fa[i].yr=b*(-1);
a--;
b++;
a=fa[0].xds*(-1)+t;
b=0;
returni;
intjiancha(DataTypex,intn)//安全性检测,检查当前情况下,修道士是否安全
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>
x.yr<
return1;
return0;
voidprint(Ltable*q,Ltable*p)//打印安全渡河的过程
DataTypea[100];
inti=1;
a[0].cw=0;
a[0].xds=0;
a[0].yr=0;
while(q!
=p)
a[i++]=q->
data;
q=q->
par;
while((--i)>
-1)
printf("
(%d%d%d)"
a[i].xds,a[i].yr,a[i].cw);
if(!
(a[i].xds==0&
a[i].yr==0&
a[i].cw==0))
{if(a[i].cw==1)
-->
(%d%d)-->
(%d%d0)\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%d1)\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);
elseprintf("
\n"
);
渡河成功!
voidwork(Ltable*p,intn,intc)
Ltable*q,*t;
DataTypetem;
inti,flag,flag1,g=0,j,count=0;
q=p->
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.cw=1-q->
data.cw;
t=q;
if(jiancha(tem,n))
flag1=1;
while(t!
if(tem.xds==t->
data.xds&
tem.yr==t->
data.yr&
tem.cw==t->
data.cw)
flag1=0;
break;
t=t->
if(flag1==1)
if(flag==0)
insertson(q,tem);
flag=1;
insertbro(q,tem);
if(tem.xds==0&
tem.yr==0&
tem.cw==0)
print(q,p);
count++;
}
}
if(count==0)
无法成功渡河,修道士好郁闷!
有%d种渡河方式。
count);
intmain()
Ltable*p;
Ltableinit(&
p);
//初始化邻接表;
intn,c;
while
(1)
请输入修道士与野人的人数n:
scanf("
%d"
&
n);
if(n==0)
请输入船可容纳的人数c:
c);
tem.xds=n;
tem.yr=n;
tem.cw=1;
insertson(p,tem);
//将初始状态作为头结点的孩子结点;
work(p,n,c);
//进行广度搜索;
#include<
/*xiudaoshi*/
/*yeren*/
/*船工*/
DataTypefa[5000];
voidprint(Ltable*q,Ltable*p);
voidwork(Ltable*p,intn,intc);
voidinsertbro(Ltable*head,DataTypex);
voidLtableinit(Ltable**head);
intmain(void)
/*初始化邻接表;
*/
/*将初始状态作为头结点的孩子结点;
/*进行广度搜索;
voidLtableinit(Ltable**head)/*初始化邻接表的操作*/
if((*head=(Ltable*)malloc(sizeof(Ltable)))==NULL);
/*动态分配空间*/
puts("
Mallocerror!
"
exit
(1);
voidinsertbro(Ltable*head,DataTypex)/*在邻接表中插入兄弟结点的操作,所有的兄弟结点都指向他们右边的结点;
}
voidprint(Ltable*q,Ltable*p)/*打印安全渡河的过程*/
-1)
a[i].cw==0))
if(a[i].cw==1)
野人过河问题算法分析
野人过河问题属于人工智能学科中的一个经典问题,问题描述如下:
有三个牧师(也有的翻译为传教士)和三个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于牧师的人数,那么牧师就会有危险.
你能不能找出一种安全的渡河方法呢?
一、算法分析
先来看看问题的初始状态和目标状态,假设和分为甲岸和乙岸:
初始状态:
甲岸,3野人,3牧师;
乙岸,0野人,0牧师;
船停在甲岸,船上有0个人;
目标状态:
甲岸,0野人,0牧师;
乙岸,3野人,3牧师;
船停在乙岸,船上有0个人;
整个问题就抽象成了怎样从初始状态经中间的一系列状态达到目标状态。
问题状态的改变是通过划船渡河来引发的,所以合理的渡河操作就成了通常所说的算符,根据题目要求,可以得出以下5个算符(按照渡船方向的不同,也可以理解为10个算符):
渡1野人、渡1牧师、渡1野人1牧师、渡2野人、渡2牧师
算符知道以后,剩下的核心问题就是搜索方法了,本文采用深度优先搜索,通过一个FindNext(…)函数找出下一步可以进行的渡河操作中的最优操作,如果没有找到则返回其父节点,看看是否有其它兄弟节点可以扩展,然后用Process(…)函数递规调用FindNext(…),一级一级的向后扩展。
搜索中采用的一些规则如下:
1、渡船优先规则:
甲岸一次运走的人越多越好(即甲岸运多人优先),同时野人优先运走;
乙岸一次运走的人越少越好(即乙岸运少人优先),同时牧师优先运走;
2、不能重复上次渡船操作(通过链表中前一操作比较),避免进入死循环;
3、任何时候河两边的野人和牧师数均分别大于等于0且小于等于3;
4、由于只是找出最优解,所以当找到某一算符(当前最优先的)满足操作条件后,不再搜索其兄弟节点,而是直接载入链表。
5、若扩展某节点a的时候,没有找到合适的子节点,则从链表中返回节点a的父节点b,从上次已经选择了的算符之后的算符中找最优先的算符继续扩展b。
二、基本数据结构
仔细阅读问题,可以发现有些基本东西我们必须把握,例如:
每时刻河两岸野人牧师各自的数目、船的状态、整个问题状态。
所以我们定义如下几个数据结构:
typedef
struct
_riverside
//
岸边状态类型
int
wildMan;
野人数
churchMan;
牧师数
}RIVERSIDE;
_boat
船的状态类型
{
}BOAT;
_question
整个问题状态
RIVERSIDE
riverSide1;
甲岸
riverSide2;
乙岸
side;
船的位置,
甲岸为-1,
乙岸为1
BOAT
boat;
船的状态
_question*
pPrev;
指向前一渡船操作
pNext;
指向后一渡船操作
}QUESTION;
用QUESTION来声明一个最基本的链表。
作者:
dick990333
发表时间:
2008-9-221:
37:
00
第5楼
三、程序流程及具体设计
本文只找出了最优解,据我所知,本问题有三种解。
如果真要找出这三种解,^_^,那就得加强对链表的操作了,比如说自己写一个动态链表类,顺便完成一些初始化工作,估计看起来会舒服些。
下面给出部分关键程序:
主函数
main()
初始化
QUESTION*
pHead
=
new
QUESTION;
pHead->
riverSide1.wildMan
3;
riverSide1.churchMan
riverSide2.wildMan
0;
riverSide2.churchMan
side
-1;
船在甲岸
pPrev
NULL;
pNext
boat.wildMan
boat.churchMan
if
(Process(pHead))
.........
遍历链表输出结果
cout<
<
成功渡河。
;
else
到底怎样才能渡河呢?
郁闷!
endl;
回收内存空间
while
(pHead)
pTemp
delete
pHead;
pHead=pTemp;
return
渡船过程,
递规调用函数FindNext(...)
BOOL
Process(QUESTION*
pQuest)
(FindNext(pQuest))
pNew
pNew->
pQuest->
riverSide
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验一 知识表示方法 实验 知识 表示 方法