问题描述
假设有 n 个修道士和 n 个野人准备渡河,但只有一条能容纳 c 人的小船,为了防止野人侵犯修道士,要求无论在何处,修道士的个数不得少于野人的人数(除非修道士个数为0)。如果两种人都会划船,试设计一个算法,确定他们能否渡过河去,若能,则给出一个小船来回次数最少的最佳方案。
解题思路
采用邻接表做为存储结构,将各种状态之间的迁移图保存下来
用一个三元组(x1, x2, x3)表示渡河过程中各个状态。其中,x1 表示起始岸上修道士个数, x2 表示起始岸上野人个数,x3 表示小船位置(0——在目的岸,1——在起始岸)。例如 (2,1,1)表示起始岸上有两个修道士,一个野人,小船在起始岸一边
用一个二元组(x1, x2)表示一个小船的状态,x1表示修道士人数,x2表示野人数量。x1≥≥x2;或者 x1=0, x2=任意数
应用广度优先搜索来查找最优解
输出所有的最优解。可能不存在,也可能有很多最优解
样例输入输出
修道士与野人测试数据免费下载,人数 n 从3到11不等
输入样例:
起始岸上有多少个传教士或野人? 3
小船上面最多承载多少人? 2
输出样例:
n = 3 c = 2 总共有 4 个解, 每一个都是来回往返两岸 11 次
(3 3 1 ) –> ( 0 2 ) –> (3 1 0 )
(3 1 0 ) <– ( 0 1 ) <– (3 2 1 )
(3 2 1 ) –> ( 0 2 ) –> (3 0 0 )
(3 0 0 ) <– ( 0 1 ) <– (3 1 1 )
(3 1 1 ) –> ( 2 0 ) –> (1 1 0 )
(1 1 0 ) <– ( 1 1 ) <– (2 2 1 )
(2 2 1 ) –> ( 2 0 ) –> (0 2 0 )
(0 2 0 ) <– ( 0 1 ) <– (0 3 1 )
(0 3 1 ) –> ( 0 2 ) –> (0 1 0 )
(0 1 0 ) <– ( 0 1 ) <– (0 2 1 )
(0 2 1 ) –> ( 0 2 ) –> (0 0 0 )
渡河成功!
(3 3 1 ) –> ( 0 2 ) –> (3 1 0 )
(3 1 0 ) <– ( 0 1 ) <– (3 2 1 )
(3 2 1 ) –> ( 0 2 ) –> (3 0 0 )
(3 0 0 ) <– ( 0 1 ) <– (3 1 1 )
(3 1 1 ) –> ( 2 0 ) –> (1 1 0 )
(1 1 0 ) <– ( 1 1 ) <– (2 2 1 )
(2 2 1 ) –> ( 2 0 ) –> (0 2 0 )
(0 2 0 ) <– ( 0 1 ) <– (0 3 1 )
(0 3 1 ) –> ( 0 2 ) –> (0 1 0 )
(0 1 0 ) <– ( 1 0 ) <– (1 1 1 )
(1 1 1 ) –> ( 1 1 ) –> (0 0 0 )
渡河成功!
(3 3 1 ) –> ( 1 1 ) –> (2 2 0 )
(2 2 0 ) <– ( 1 0 ) <– (3 2 1 )
(3 2 1 ) –> ( 0 2 ) –> (3 0 0 )
(3 0 0 ) <– ( 0 1 ) <– (3 1 1 )
(3 1 1 ) –> ( 2 0 ) –> (1 1 0 )
(1 1 0 ) <– ( 1 1 ) <– (2 2 1 )
(2 2 1 ) –> ( 2 0 ) –> (0 2 0 )
(0 2 0 ) <– ( 0 1 ) <– (0 3 1 )
(0 3 1 ) –> ( 0 2 ) –> (0 1 0 )
(0 1 0 ) <– ( 0 1 ) <– (0 2 1 )
(0 2 1 ) –> ( 0 2 ) –> (0 0 0 )
渡河成功!
(3 3 1 ) –> ( 1 1 ) –> (2 2 0 )
(2 2 0 ) <– ( 1 0 ) <– (3 2 1 )
(3 2 1 ) –> ( 0 2 ) –> (3 0 0 )
(3 0 0 ) <– ( 0 1 ) <– (3 1 1 )
(3 1 1 ) –> ( 2 0 ) –> (1 1 0 )
(1 1 0 ) <– ( 1 1 ) <– (2 2 1 )
(2 2 1 ) –> ( 2 0 ) –> (0 2 0 )
(0 2 0 ) <– ( 0 1 ) <– (0 3 1 )
(0 3 1 ) –> ( 0 2 ) –> (0 1 0 )
(0 1 0 ) <– ( 1 0 ) <– (1 1 1 )
(1 1 1 ) –> ( 1 1 ) –> (0 0 0 )
渡河成功!