传教士和野人问题实验报告

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

1.上机内容

传教士与野人问题求解(宽度搜索算法)

二问题背景:

从前有一条河,河的左岸有m个传教士(Missionary)和m个野人(Cannibal),和一艘最多可乘n人的小船。约定左岸,右岸和船上或者没有传教士,或者野人数量少于传教士,否则野人会把传教士吃掉。

三实验内容:

编程,接收m和n,搜索一条可让所有的野人和传教士安全渡到右岸的方案,例如下图:

(M表示传教士(Missionary),C 表示野人(Cannibal))

初态目标

Left Bank River Right

bank

Left

Bank

River Right

bank

M…. M….

C…. C….

注:本实验的举例均以3个传教士和3个野人同在左岸作为初始状态。

四实验方案和算法:

1.数据结构:

本实验需要用到的数据结构主要是队列和堆栈,其实现均包含于dso.h头文件中,分别命名为class stack和class queue。

2.宽度搜索算法:

(1)结点结构:

class Move {

public:

int missionary; //要移动的传教士数量

int cannibal; //野人

};

class ElemType : Move { //继承Move类,获得传教士,野人数据成员。

private:

bool boat; //船是否在左岸?

public:

ElemType* flag; //标示前一状态即扩展出本结点的父结点信息

ElemType(int MAX_PEOPLE) { //创建初始状态

missionary = cannibal = MAX_PEOPLE;

boat = true;

flag = NULL;

}

……

在这里,Elemtype集成了Move,从而获得Move类的传教士和野人数据成员。以上两个类的数据成员用于保存所有扩展生成的结点。其中missionary表示表示左岸上传教士的树目,cannibal表示左岸上野人的树目,boat表示船在哪个岸上(其中true表示在左岸,这是船的初始状态,表示false在右岸), flag 用于标示前一状态即扩展出本结点的父结点信息,以便最后回搜找出解的

路径。

举例说明:假设左岸有3个传教士和3个野人,小船最多可乘2人。把当前左岸的状态抽象为:(3,3,1),前两个"3"代表左岸有3个传教士和3个野人,1代表船在左岸。很明显,目标状态为(0,0,0),表示左岸的传教士和也人数目都是0,而船在右岸。

(2)船的行动规则(successor function):

把每一次可行的渡船方案作为行动规则,用Move类的(m,c)表示。行动规则的两位数分别代表要移动的传教士,野人的数量。对于固定大小的船,其装载能力是一定的,所以它的行动规则空间也是一定的。在这里,用MoveGroup类的构造函数构造出所有的行动规则。

注意,这里MoveGroup类中的Move对象只有500的可用空间,所以,输入的传教士和野人数目构成的行动规则不能超过500种。

(3)宽度优先算法:

实验的主要搜索算法由ANSWER类的构造函数实现,这里主要用到了OPEN和CLOSED队列,以及一个临时的TEMP堆栈。其中,OPEN表用于存放扩展结点,CLOSED表用于存放被扩展结点,TEMP则用于用于记录成功搜索的路径。

搜索过程大致如下描述:先构造初始结点以及船的行动规则,初始结点入OPEN队列,以宽度优先依次搜索OPEN队列头结点的子结点,同时保存受访问结点的父结点信息,知道搜索到目标结点或者无解为止。

算法框图如下所示:

3 程序界面和功能说明:

程序运行环境为DOS控制台,运行开始以后,程序提示输入需要坐船的传教士和野人数目,例如输入3表示有3个传教士和3个野人。

用户按回车键以后,程序继续提示输入船的装载能力,例如输入2表示这个船依次最多可以坐2人。注:一般情况下,船的装载能力应该少于传教士或野人的数量,而且一般为偶数。

程序开始运行时的界面截图:

程序运行结束时的界面截图:

输出文件示例:

Left(3, 3) | (0, 0)Right

[Step 1]

Move 0 missionaries and 2 cannibals to the right side. Left(3, 1) | (0, 2)Right

[Step 2]

Move 0 missionaries and 1 cannibals to the left side. Left(3, 2) | (0, 1)Right

[Step 3]

Move 0 missionaries and 2 cannibals to the right side. Left(3, 0) | (0, 3)Right

[Step 4]

Move 0 missionaries and 1 cannibals to the left side. Left(3, 1) | (0, 2)Right

[Step 5]

Move 2 missionaries and 0 cannibals to the right side. Left(1, 1) | (2, 2)Right

[Step 6]

Move 1 missionaries and 1 cannibals to the left side. Left(2, 2) | (1, 1)Right

[Step 7]

Move 2 missionaries and 0 cannibals to the right side. Left(0, 2) | (3, 1)Right

[Step 8]

Move 0 missionaries and 1 cannibals to the left side. Left(0, 3) | (3, 0)Right

[Step 9]

Move 0 missionaries and 2 cannibals to the right side. Left(0, 1) | (3, 2)Right

[Step 10]

Move 0 missionaries and 1 cannibals to the left side.

相关文档
最新文档