- 1、本文档共5页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
野人过河问题描述如下有三个传教士和三个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于.doc
传教士和野人渡河问题
刘宪国 050422023
野人过河问题描述如下: 有三个传教士和三个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于传教士的人数,那么传教士就会有危险.
一、算法分析
先来看看问题的初始状态和目标状态,假设分为甲岸和乙岸:
初始状态:甲岸,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; // 野人数
int churchMan; // 传教士数
}RIVERSIDE;
typedef struct _boat{ // 船的状态类型
int wildMan; // 野人数
int churchMan; // 传教士数
}BOAT;
typedef struct _question{ // 整个问题状态
RIVERSIDE riverSide1; // 甲岸
RIVERSIDE riverSide2; // 乙岸
int side; // 船的位置, 甲岸为-1, 乙岸为1
BOAT boat; // 船的状态
_question* pPrev; // 指向前一渡船操作
_question* pNext; // 指向后一渡船操作
}QUESTION;
用QUESTION来声明一个最基本的链表。
三、程序流程及具体设计
下面给出部分关键程序:
int main()// 主函数
{ // 初始化
QUESTION* pHead = new QUESTION;
pHead-riverSide1.wildMan = 3;
pHead-riverSide1.churchMan = 3;
pHead-riverSide2.wildMan = 0;
pHead-riverSide2.churchMan = 0;
pHead-side = -1; // 船在甲岸
pHead-pPrev = NULL;
pHead-pNext = NULL;
pHead-boat.wildMan = 0;
pHead-boat.churchMan = 0;
if (Process(pHead))
{ // ......... 遍历链表输出结果
……
……
}
cout成功渡河。;
}
else
cout到底怎样才能渡河呢? 郁闷!
pNext;
delete pHead;
pHead=pTemp;
}
pHead = NULL;
return 0;
}
// 渡船过程, 递规调用函数FindNext(...)
BOOL Process(QUESTION* pQuest) {
if (FindNext(pQuest))
{
QUESTION* pNew = new QUESTION;
pNew-riverSide1.wildMan = pQuest-riverSide1.wildMan + pQuest-boat.wildMan*(pQuest-side);
pNew-riverSide1.chur
文档评论(0)