- 1、本文档共11页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
PAGE
PAGE 11
3.修道士与野人问题
题目:
这是一个古典问题。假设有n个修道士和n个野人准备渡河,但只有一条能容纳c人的小船,为了防止野人侵犯修道士,要求无论在何处,修道士的个数不得少于野人的人数(除非修道士个数为0)。如果两种人都会划船,试设计一个算法,确定他们能否渡过河去,若能,则给出一个小船来回次数最少的最佳方案。
需求分析
题目要求:
用一个三元组(x1,x2,x3)表示渡河过程中各个状态。其中,x1表示起始岸上修道士个数,x2表示起始岸上野人个数,x3表示小船位置(0——在目的岸,1——在起始岸)。
采用广度搜索法,得到首先搜索到的边数最少的一条通路。
输出数据
若问题有解(能渡过河去),则输出一个最佳方案。用三元组表示渡河过程中的状态,并用箭头指出这些状态之间的迁移:
初始状态→…中间状态→目的…状态
求出所有的解。
程序测试:用户输入修道士与野人个数以及一条船可容纳的人数,则程序输出可行的渡河状态图并输出最优解,程序最后给出可行解的个数。
注意:
程序的输出格式严格按照三元组的形式,给出状态变迁图
必须采用广度搜索算法
设计
2.1设计思想
存储结构
定义一个结构体,用于存放各个时刻的状态
typedef struct
{
int x1;//修道士
int x2;//野蛮人
int x3;//状态
}DataType;
用邻接表存储结构实现图的操作,其存储结构为:
typedef struct Node
{
int dest; //邻接表的弧头结点序号
struct Node *next;
}Edge; //邻接表单链表的结点结构体
typedef struct
{
DataType data; //结点数据元素
int sorce; //邻接表的弧尾结点序号
Edge *adj; //邻接边的头指针
int pre; //指向此点的点的序号
}AdjLHeight; //数组的数据元素类型结构体
typedef struct
{
AdjLHeight a[10000]; //邻接表数组
int numOfVerts; //结点个数
int numOfEdges; //边个数
}AdjLGraph; //邻接表结构体
基本思想
由题意知,数据结构选用图较为合理,题中图的结点数目较大且边的数目远小于相同结点的完全图的边数,因此采用图的邻接表存储结构效率较高
根据给出的小船上的位置数量,生成小船上的安全状态,即在船上的时候修道士的人数也要比野人的数量要多(除非修道士人数为0)。
让修道士跟野人上船后,检测当船到达对岸后,两岸修道士的安全状态,若修道士安全,则将此结点加入到邻接表中
渡船优先规则:起始岸一次运走的人越多越好(即起始岸运多人优先),同时野人优先运走;目的岸一次运走的人越少越好(即目的岸运少人优先),同时修道士优先运走
采用广度搜索法,得到首先搜索到的边数最少的一条通路
举例说明:
当n=3;c=2时,可用树状图来表示运送过程并用广度搜索法来查找最佳方案
(f表示运过去之后右岸的总人数,P从始岸到对岸;0从对岸到始岸)
f=3 Q
f=3 Q01
f=2 P02
f=1 Q01
f=1 Q11
f=1 P01
f=2 P11
(3,3,1)
(3,2,0)
(2,2,0)
(3,1,0)
(3,2,1)
(3,0,0)
f=3 P02
(3,1,1)
f=2 Q01
(1,1,0)
f=4 P20
(2,2,1)
f=2 Q11
(1,1,0)
f=4 P20
(2,2,1)
f=2 Q11
1
(0,2,0)
f=4 P20
(0,3,1)
f=3 Q01
(0,1,1)
f=5 P02
(0,2,1)
f=4 Q01
(0,0,0)
f=3 Q01
(1,1,1)
f=4 Q10
2.2 设计表示法
过程或函数调用关系图
main → work → check → print
基于数据结构的操作组
该程序数据结构相对简单,只运用了邻接表结构的图,work()函数建立一个广度表,实现广度搜索算法;check()函数用于检查各个状态下修道士是否安全;print()函数打印安全渡河的过程
过程或函数接口规格说明
void work(AdjLGraph *p) //广搜建立表
int check (DataType x) //检查当前情况下,修道士是否安全
int print(AdjLGraph *p,int g) //打印安全渡河
文档评论(0)