传教士和野人过河
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验报告
一、实验名称:
传教士和野人过河
二、实验目的:
这是经典的过河方案规划问题,通过本实验的设计与编程实现让学生掌握基
于状态空间知识表示方法的一般搜索策略。
三、实验内容:
设有3个传教士和3个野人同在河的左岸,他们都要到对岸去;河里只有
一条船,他们都会划船,但每次渡船至多只能乘两人;如果在任何一岸上,也认的数量超过传教士,野人就要吃掉传教士,要求设计算法,用船将3
个传教士和3个野人安全的从左岸移到右岸。
四、实验设计
(一)所用的语言:c++语言
(二)数据结构
节点状态用列表(m,c,b)表示,其中m表示传教士在左岸的人数; c表
示野人在左岸的人数;b表示船是否在左岸,当b=1时,表示船在左岸,
当b=0时,表式船在右岸。
初始状态:(3,3,1)
目标状态: (0,0,0)
操作算子:船上人数组合(m,c)共5种(1,0),(1,1),(2,0),
(0,1),(0,2)
因此算法有10种
1)从右岸向左岸过1个传教士,0个野人
2)从右岸向左岸过1个传教士,1个野人
3)从右岸向左岸过2个传教士,0个野人
4)从右岸向左岸过0个传教士,1个野人
5)从右岸向左岸过0个传教士,2个野人
6)从左岸向右岸过1个传教士,0个野人
7)从左岸向右岸过1个传教士,1个野人
8)从左岸向右岸过2个传教士,0个野人
9)从左岸向右岸过0个传教士,1个野人
10)从左岸向右岸过0个传教士,2个野人
状态节点: typedef struct st
{
int m;//传教士
int c;//野人
int b;//船左
}state;//状态
将有效的节点存储在树中
Tree 中的节点
typedef struct hnode
{
state s;
struct hnode *left;
struct hnode *right;
}node;
Open表,closed表用队列存储
//定义队列中的节点
typedef struct Queuenode
{
node * np;
struct Queuenode* next;
}Qnode;//队列中节点
//定义队列
typedef struct Queue
{
Qnode *front;
Qnode *rear;
}queue;
(三)算法流程
1.用起始节点(3,3,1) 初始化tree,初始化open表,closed表。
2.把tree中节点放到open表中。
3.如果open表为空,则失败,退出,无解。
4.从open表中取对头元素q。
5.扩展节点q,对q中的节点值,进行五步操作计算,得到五个节点。
逐个检查五个节点
1)如果该节点不合法,则继续检查下一个节点;如果合法,进行下一步。
2)如果open表中含有节点,则修改q节点的左指针为查找到节点的地址;
否则,如果此节点的在closed表中,则生成一个新节点,为新节点赋
值。如果为此树中q节点的第一孩子,则将该新节点赋值给q的左孩
子;否则将其赋值给q的左孩子的右孩子的右孩子。将该新节点加入
到open表中。
否则,继续检查下一个节点。
6.把节点q从open表中移出,并把它放入closed的扩展节点表中。
7.取出open表队头节点q,判断是否为目标节点,如果是则返回,终止搜
索,并且将其加入到closed表中;否则,转向步骤5。
8.用栈遍历tree,将结果输出。
五、实验结果
如下图:总共有四种方法完成本题目