前言:这一个经典的问题,可以把问题转换成数据结构中的 来解决。本博客节选自我去年7月份的数据结构报告


问题描述

假设有 n 个修道士和 n 个野人准备渡河,但只有一条能容纳 c 人的小船,为了防止野人侵犯修道士,要求无论在何处,修道士的个数不得少于野人的人数(除非修道士个数为0)。如果两种人都会划船,试设计一个算法,确定他们能否渡过河去,若能,则给出一个小船来回次数最少的最佳方案。

解题思路

  1. 采用邻接表做为存储结构,将各种状态之间的迁移图保存下来

  2. 用一个三元组(x1, x2, x3)表示渡河过程中各个状态。其中,x1 表示起始岸上修道士个数, x2 表示起始岸上野人个数,x3 表示小船位置(0——在目的岸,1——在起始岸)。例如 (2,1,1)表示起始岸上有两个修道士,一个野人,小船在起始岸一边

  3. 用一个二元组(x1, x2)表示一个小船的状态,x1表示修道士人数,x2表示野人数量。x1≥\gex2;或者 x1=0, x2=任意数

  4. 应用广度优先搜索来查找最优解

  5. 输出所有的最优解。可能不存在,也可能有很多最优解


样例输入输出

修道士与野人测试数据免费下载,人数 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 )
渡河成功!


设计思路

1) 初始化:用户输入起始岸上的修道士和野人的人数 n,再输入每一条小船容纳的人数 c
2) 依据 n,构造出所有可能存在的三元组(x1, x2, x3),即所有修道士的安全状态,然后以 这一些三元组为数据成员之一,构造出 Graph 中相应的 Vertex
3) 依据 c,构造出所有可能存在的小船(x1, x2),保证船上所有修道士的安全
4) 依据在上述两个步骤构造出的 Vertex,小船,和安全检测条件,可以构造出所有存在 Edge
5) 上述 3 个步骤已经把整个图(邻接表)构造好了,应用广度优先搜索找到所有最优解
6) 把所有最优解输出到文档中
7) 结束

经过对于问题的思考,不难发现这个问题的逻辑结构是图。顶点封装三元组,边实际上是小船的“抽象”,小船连接着两岸,同样边连接着两个顶点。


talk is cheap, show me the code

下载 野人与修道士 C++完整工程项目及源代码,需要两个下载积分哟~

有6个头文件,代表6个类
有一个main.cpp

  • Data.h:封装一个三元组(x1, x2, x3)
  • Boat.h:封装一条船,一条船的本质是——两个 Vertex 之间的纽带
  • Vertex.h:封装一个结点。数据成员包含 Data 类,Data 类的顺序数组 path,指向第 一个相邻顶点的指针。主要功能包括:检查重复,打印 path,Vertex 状态转移函数(增 减 Boat)
  • AdjLWGraph.h:封装整个图。主要功能包括:基础的与图有关的插入、删除等操作, 构造 Vertex,构造 Boat,构造 Edge,判断一个 Data 三元组是否安全,解决问题(广度 优先搜索),打印所有解
  • SeqList.h:封装一个顺序的动态数组
  • SeqQueue.h:封装一个顺序的静态数组

核心算法伪代码





算法分析

证明算法的正确性:

BFS 找出的第一个解肯定是 optimal result。因为 BFS 是“一层一层往下”搜索的,第一个 搜到解一定是“层数”最少的解。

假设第一个最优解的渡河次数 = a,如果搜索到了一个解的渡河次数 > a,那么搜索结束。 至此,所有的最优解全部找到。

算法复杂度

修道士与野人问题——C++源代码,伪代码,详细分析相关推荐

  1. 修道士和野人java_野人与修道士问题——详细分析与C++源代码

    前言:这一个经典的问题,可以把问题转换成数据结构中的 图 来解决.本博客节选自我去年7月份的数据结构报告 问题描述 假设有 n 个修道士和 n 个野人准备渡河,但只有一条能容纳 c 人的小船,为了防止 ...

  2. 修道士和野人java_修道士和野人问题

    休闲时刻看看神经网络方面的书,发现了修道士和野人的问题,不禁勾引起我写算法的欲望,曾经的三只大老虎三只小老虎过河问题.人狼羊白菜过河问题.汉诺塔.哈夫曼等等各种算法瞬间在脑海中约隐约现,修道士和野人问 ...

  3. 修道士和野人问题:所有解、启发求解、简单界面

    一.作业任务 修道士和野人问题:设有三个修道士和3个野人来到河边,打算用一条船从河的左岸渡到河的右岸去.但该船每次只能装载两个人,在任何岸边野人的数目都不得超过修道士的人数,否则修道士就会被野人吃掉. ...

  4. 人工智能实践作业-修道士和野人过河问题

    人工智能实践作业-修道士和野人过河问题: 用编程语言编写和调试一个基于深度优先搜索法的解决"野人与传教士过河"问题的程序.目的是学会运用知识表示方法和搜索策略求解一些考验智力的简单 ...

  5. 1. A星算法解决修道士与野人问题

    A星算法解决修道士与野人问题 1. 运行环境 CPU:I5-10400 内存:16GB 系统:Win10 64位专业版,20H2 IDE:Vistual Studio 2019专业版 2. 问题描述 ...

  6. 用状态空间方法求解修道士与野人问题

    目录 一.状态空间表示法回顾 1.问题状态空间的构成 2.用状态空间表示问题的步骤 二.使用状态空间法求解修道士与野人问题 1.问题描述 2.状态空间求解步骤 总结 一.状态空间表示法回顾 状态空间表 ...

  7. 2.修道士和野人问题

    2.修道士和野人问题:设有三个修道士和3个野人来到河边,打算用一条船从河的左岸渡到河的右岸去.但该船每次只能装载两个人,在任何岸边野人的数目都不得超过修道士的人数,否则修道士就会被野人吃掉.假设野人服 ...

  8. 修道士和野人java_修道士与野人问题(BFS广度搜索)

    #include "iostream.h" #include "string.h" //定义一个状态节点 typedef struct //存储各个状态 { i ...

  9. 使用dfs求解修道士和野人问题

    原文链接: 使用dfs求解修道士和野人问题 上一篇: js Set 的使用 下一篇: VMware 挂载U盘 1.问题描述 :这是一个古典问题.假设有n个道士和n个野人准备渡河.但只有一条能容纳c人的 ...

最新文章

  1. CUDA 并行计算优化策略总结
  2. 【错误记录】Android Studio 编译报错 ( Could not determine java version from ‘11.0.8‘. ② | 升级 Gradle 版本 )
  3. Python3快速入门(五)——Python3函数
  4. UA OPTI512R 傅立叶光学导论14 Wiener-Khinchine定理,Rayleigh定理与矩定理
  5. apkTool反编译apk碰到的问题
  6. idea提示 cannot resolve symbol “println
  7. react笔记组件属性传递机制(四)
  8. jsp页面播放服务器视频
  9. 在WIN7下用NETSH命令有效防止ARP攻击
  10. 简单演示matlab生成三维平面的命令mesh
  11. HDLM for AIX安装
  12. C# 字符串转JSON格式
  13. 如何使用 DiskGenius 合并分区
  14. 自己做量化交易软件(18)小白量化平台
  15. 集成建行龙支付(2019.01.24更新)
  16. java 不登录购物车_java-没有用户登录时存储购物车(playframework疑问)
  17. 计算机 分类号,中图法分类号(计算机,自动化)(CLC number (computer, automation)).doc...
  18. 很火的华为太空表网站源码
  19. 裁剪rplidar的扫描数据
  20. Leetcode 1419:数青蛙(超详细的解法!!!)

热门文章

  1. dedecms 5.7SP1实现获得当前栏目父栏目ID
  2. MLflow基于Windows通过Docker和Minio搭建mlflow server
  3. 前端项目中碰到的难题bug
  4. VS Code,PyCharm与GitHub同步
  5. 新地理信息时代的信息化测绘
  6. Aegisub的视频窗口详解
  7. 【精品】服务端 架构演进 历程
  8. 关于Rosetta的那些事
  9. 中学教学01教学概述02教学过程03教学原则与方法
  10. 远程linux桌面的工具xshell,Xshell如何远程桌面连接Linux系统 Xshell远程桌面连接Linux系统操作流程...