野人与修道士问题的Ruby实现

问题描述:
河左岸有三个修道士,三个野人和一条船,假定船最多只能运两个人,且任何岸边的野人数目不得超过修道士,否则修道士就会被野人吃掉。
如何才能把修道士和野人都运到右岸?


Savage.rb



SAVAGE    = 0
BOANERGES = 1
DEEP      = 5

#记录状态
class Status
 @@StatusList = Array.new
 @@Pos = -1
 
  attr_writer :nSavage          #岸边野人的数量,全部到对岸为0
  attr_writer :nBoanerges       #岸边传教士的数量,全部到对岸为0
  attr_writer :nSide            #船的位置,在此岸为-1,对岸为1
  attr_writer :nMoveSavage      #渡河的野人的数量,用于递归时记录操作状态
  attr_writer :nMoveBoanerges   #渡河的传教士的数量,用于递归时记录操作状态 

  attr_reader :nSavage          
  attr_reader :nBoanerges       
  attr_reader :nSide            
  attr_reader :nMoveSavage      
  attr_reader :nMoveBoanerges   
 
  def initialize()
   @nSavage        =  3
   @nBoanerges     =  3
   @nSide          = -1
   @nMoveSavage    =  0
   @nMoveBoanerges =  0
 end
 
  def Status.getList()
   return @@StatusList
 end
 
  def Status.getPos()
   return @@Pos
 end
 
  def Status.addStatus(stat)
   @@StatusList.push(stat)
   @@Pos += 1
 end
 
 def Status.delStatus()
  @@StatusList.pop()
  @@Pos -= 1
 end
end

class Ship
 def Ship.hasNextStep(stat)
  store = [[],[],[],[],[]]
  
  if stat.nSide == -1 then
   store[0][SAVAGE]    = 2
      store[0][BOANERGES] = 0
      store[1][SAVAGE]    = 1
      store[1][BOANERGES] = 1
      store[2][SAVAGE]    = 0
      store[2][BOANERGES] = 2
     store[3][SAVAGE]    = 1
      store[3][BOANERGES] = 0
      store[4][SAVAGE]    = 0
     store[4][BOANERGES] = 1
  elsif stat.nSide == 1
      store[0][SAVAGE]    = 0
      store[0][BOANERGES] = 1
      store[1][SAVAGE]    = 1
      store[1][BOANERGES] = 0
      store[2][SAVAGE]    = 0
      store[2][BOANERGES] = 2
      store[3][SAVAGE]    = 1
      store[3][BOANERGES] = 1
      store[4][SAVAGE]    = 2
      store[4][BOANERGES] = 0  
  end

  iStart = 0
    if stat.nMoveSavage == 0 && stat.nMoveBoanerges == 0
     iStart = 0
    else
     for iStart in 0...DEEP
       puts iStart
    if stat.nMoveSavage == store[iStart][SAVAGE] && stat.nMoveBoanerges == store[iStart][BOANERGES]
         break
        end
      end
      iStart += 1
  end
   
  if (iStart < DEEP)
   i = 0
   for i in iStart...DEEP
    nSideSavage      = stat.nSavage + stat.nSide * store[i][SAVAGE]
        nSideBoanerges   = stat.nBoanerges + stat.nSide * store[i][BOANERGES]
        nBesideSavage    = 3 - nSideSavage
        nBesideBoanerges = 3 - nSideBoanerges

        #传教士数量大于等于野人或为零
        if ((nSideSavage   <= nSideBoanerges   || nSideBoanerges   == 0) &&
            (nBesideSavage <= nBesideBoanerges || nBesideBoanerges == 0) &&
             nSideSavage   >= 0 && nSideBoanerges >= 0 && nBesideSavage >= 0 && nBesideBoanerges >= 0) then
         #如果本此解等于上次,放弃
          if Status.getPos > 0
           if (Status.getList()[Status.getPos - 1].nMoveBoanerges == store[i][BOANERGES] &&
                Status.getList()[Status.getPos - 1].nMoveSavage    == store[i][SAVAGE])
               next
            end
          end
          break
        end
   end
   
   if i < DEEP
     stat.nMoveSavage    = store[i][SAVAGE]
        stat.nMoveBoanerges = store[i][BOANERGES]
        return true
      end
    end

    return false;  
 end
 
 #递归函数
 def Ship.find(stat)
   if hasNextStep(stat)
     pNew = Status.new
      pNew.nSavage        = stat.nSavage + stat.nMoveSavage * stat.nSide
      pNew.nBoanerges     = stat.nBoanerges + stat.nMoveBoanerges * stat.nSide
      pNew.nSide          = stat.nSide * -1
      pNew.nMoveSavage    = 0
      pNew.nMoveBoanerges = 0
      Status.addStatus(pNew)
     
      if pNew.nSavage == 0 && pNew.nBoanerges == 0
        Status.delStatus()
       return true
      end
      return find(pNew)
    else
      if Status.getPos == 0
       return false
      end
      Status.delStatus()

      return find(Status.getList()[Status.getPos])
    end
    return true
 end
end

initStat = Status.new
Status.addStatus(initStat)
if (Ship.find(initStat))
 puts "渡河过程如下:"
 Status.getList().each do |stat|
  print "下次渡河方向:", (stat.nSide == -1) ? "-->" : "<--", " 人数:野人", stat.nMoveSavage, " 传教士", stat.nMoveBoanerges, " 当前此岸野人数:", stat.nSavage, " 传教士数:", stat.nBoanerges, "\n"
 end
else
 puts "此题无解"
end
print "Press ENTER to return."
$stdin.gets

传教士与野人过河问题(numpy、pandas) 传教士与野人过河问题(numpy、pandas) 可自定义输入 有完整代码 A*算法 阅读详情

相关推荐

人工智能——状态空间搜索及状态空间表示法

图中,节点Sk表示状态,状态之间的连接采用有向弧(Arc),弧上标以操作数OK来表示状态之间的转换关系。根据上述分析,共有16个合法状态和允许的操作,可以划出传教士和食人者问题的状态空间图,如图所示。(5)当状态数量不是很大时,按问题的有序元组画出状态空间图,依照状态空间图搜索求解。(5)当状态数量不是很大时,按问题的有序元组画出状态空间图,依照状态空间图搜索求解。(4)估计全部的状态空间数,并尽可能列出全部的状态空间或予以描述之。问题的状态可以用一个三元数组来描述,以左岸的状态来标记,即。

人工智能AI技术 2万+

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

一.作业任务 修道士和野人问题:设有三个修道士和3个野人来到河边,打算用一条船从河的左岸渡到河的右岸去。但该船每次只能装载两个人,在任何岸边野人的数目都不得超过修道士的人数,否则修道士就会被野人吃掉。假设野人服从任何一种过河安排,请规划出使全部6人安全过河的方案。 问题提示:应用状态空间表示和搜索方法时,可用(Nm,Nc)来表示状态描述,其中Nm,Nc分别为传教士和野人的人数。初始状态为(3,3)...

weixin_44001813的博客 1万+

传教士与野人python

"传教士与野人"问题是一个经典的逻辑谜题,源于数学和计算机科学中的约束满足问题。在这个问题中,有n个传教士和n个野人,他们必须通过一条河,只有一条能载m个人(m小于或等于n)的小船。规则是不允许在任何一侧出现野人多于传教士的情况,以防传教士被野人杀害。这个问题的目的是找出一种安全的渡河策略。 在Python中解决这个问题,通常会用到搜索算法,如深度优先搜索(DFS)、广度优先搜索(BFS)或者A*搜索。这些算法能够遍历所有可能的状态,寻找满足条件的解决方案。我们需要定义状态,包括当前在河的哪一侧、船上的人数以及各有多少传教士和野人。接着,我们会定义一个转移函数,用于模拟小船在河两岸间移动,并检查每个状态是否符合安全规则。我们需要一个搜索策略来遍历状态空间,找到目标状态(所有人都到达对岸)。

修道士和野人问题——人工智能的状态空间图问题

问题:为什么将状态空间的约束条件定为 m=3或m=0或m=n?3. 左右两边同时都有野人和修道士,此时只能使m=n。1. 左边全野人,右边全修道士,此时m=3。2. 左边全修道士,右边全野人,此时m=0。

Aiden_Tyler的博客 6661

修道士野人问题

c++实现的修道士野人问题 河的左岸有N个野人和N个修道士以及一条小船,修道士们想用这条小船把所有的人都运到河的右岸,但又受到以下限制:  修道士和野人都会划船,但船一次只能载C人。  在任何岸边,为了防止野人侵犯修道士,野人数不能超过修道士数,否则修道士将会被野人吃掉。 假定野人愿意服从任何一种过河的安排,本设计的主要任务是规划出一种确保修道士安全的过河方案。

修道士与野人问题

修道士与野人过河问题,包括界面编写。

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

用状态空间图求解修道士与野人问题

jjsd__gulugulu的博客 1万+

修道士与野人渡河问题 数据结构

用三维数组STATE(0:n,0:n,0:n)代表渡河过程中所有状态(合法的和非法的)。STATE(x1,x2,x3)为真,表示该状态已经出现过(“已达”);为假,表示未曾出现过(“未达”)。

修道士和野人问题

题目: 设在河的一岸有三个野人、三个修道士和一条船,修道士想用这条船把所有的人运到河对岸,但受以下条件的约束: 一是修道士和野人都会划船,但每次船上至多可载两个人; 二是在河的任一岸,如果野人数目超过修道士数,修道士会被野人吃掉。 如果野人会服从任何一次过河安排,请规划一个确保修道士和野人都能过河,且没有修道士被野人吃掉的安全过河计划。 代码一(暴力搜索): #include <iostre...

qq_30534935的博客 1万+

Profinet从站开发初体验:用p-net开源库和树莓派快速搭建一个IO设备模拟器

本文详细介绍了如何使用p-net开源库和树莓派快速搭建Profinet从站IO设备模拟器。从开发环境准备、p-net源码编译到设备模拟器功能实现,提供了全流程实战指南,帮助开发者快速掌握工业通信协议开发技巧,适用于工业自动化领域的设备互联测试与验证。

weixin_30384217的博客 383

家庭路由器从入门到精通:连接设置、优化排障全指南

路由器作为家庭网络的核心枢纽,其工作原理基于NAT(网络地址转换)和DHCP(动态主机配置协议)两大关键技术。NAT负责将公网IP转换为多个内网IP,实现多设备共享上网;DHCP则自动为接入设备分配IP地址,简化网络配置。这些技术共同构建了稳定、安全的局域网环境,其价值在于为智能家居、在线办公、高清影音和游戏娱乐等场景提供可靠的网络基础。理解路由器的物理连接、后台设置与故障排查逻辑,是优化Wi-Fi信号覆盖、提升网络性能、保障家庭网络安全的关键。本文以路由器配置与排障为核心,详细解析从WAN/LAN口区分、

weixin_33393017的博客 404

状态空间表示法----野人与修道士

状态空间法的应用修道士(Missionaries)和野人(Cannibals)问题   在河的左岸有N个传教士(M)、N个野人(C)和一条船(Boat),传教士们想用这条船把所有人都运过河去,但有以下条件限制:  (1)修道士和野人都会划船,但船每次最多只能运K个人;  (2)在任何岸边野人数目都不能超过修道士,否则修道士会被野人吃掉。   假定野人会服从任何一种过河安排,请规划出一个确保修道士安...

轻尘 2万+

用于可靠的钙钛矿薄膜瞬时光致发光模拟的拟合程序

简介 对光激发后的电荷载流子动态的研究对于确定太阳能电池的几个特性至关重要,例如,体和界面重组的数量以及向电荷传输层转移过程的速度。 瞬态光致发光(trPL)是用于研究这些特性的最流行的表征方法之一。 该实验是通过在样品上照射几纳秒的激光脉冲,并记录一段时间内的发光情况来进行的。辐射性重组的光生电荷载流子将引起太阳能电池的光子发射,而非辐射性重组的电荷载流子将不会对发光作出贡献。因此,可以测量到强度随时间递减的光致发光瞬态。(见图1表示trPL的测量和它的输出)。 图1. 一...

FluximAG的博客 2362

人工智能:状态空间图(超详细经典例题讲解,通过例题教会你如何解决状态空间图问题)

状态空间常记为三元组:。 其中,S为初始状态的集合,F为操作的集合,G为目标状态的集合。 问题的状态空间图是一个描述该问题全部可能的状态及相互关系的有向图。 如考虑操作的代价,状态空间图就是一个赋值有向图。1、一个猎人要带着一只狼、一只羊、一捆草过河,但是人不在的时候,狼会吃羊、羊会吃草,猎人每次只能带一样东西过河。试构造状态空间图,并给出他们能顺利过河的方案。对于这种过河的题目,我们一般默认刚开始都在左岸,也只用分析左岸的情况,因为右岸的情况可以根据左岸的情况推出,比如左岸有一个狼人和一只羊......

俊夫小瞳的博客 2万+

华为eNSP Pro实战:NE/CE设备SSH远程配置避坑指南

本文针对华为eNSP Pro用户在模拟多台NE路由器或CE交换机时遇到的浏览器卡顿问题,提供了详细的SSH远程配置避坑指南。通过对比浏览器与SSH客户端的资源占用和操作体验,文章详细阐述了为NE和CE设备配置SSH服务的关键步骤、命令差异及常见错误排查方法,旨在帮助用户提升实验效率,实现稳定高效的远程管理。

weixin_29196891的博客 220

量化投资之工具篇一:Backtrader从入门到精通(1)-手把手教你零基础实现一个策略案例

Backtrader是重要的量化框架,本文记录学习该框架的笔记,内容主要基于Backtrader的网站指导文档。虽然该框架目前用于量化投资领域,但是可以作为数据处理的基本架构,进行改造后用于各种数据的处理,尤其适用于对原始数据处理完成后应用一定的策略进行预测以及可视化处理。 1、简介 Backtrader的特点,就是两点: 1、易于使用; 2、参见第1条。 那么如何使用Backtrader呢?比把大象装进冰箱复杂点,一共4步: 创建一个Cerebro引擎: 加入一个Strategy...

仓鼠王的博客 5万+

状态空间法——野人和传教士的问题

设有3 个传教士和3 个野人来到河边,打算乘一只船从右岸渡到左岸去。该船的负载能力为两人。在任何时候,如果野人人数超过传教士人数,那么野人就会把传教士吃掉。如何用状态空间法来表示该问题?给出具体的状态表示和算符。 第一步 根据题目要求设置好约束条件 例如通过船的负载能力为两人得出: 船上的人M(传教士)+C(野人)小于等于2 第二步 用三个参数表示左岸转状态 并且列出所有可用的状态 第三步 列出所有的操作集 从左岸划向右岸 +从右岸划向左岸 =共10种操作集合(详情请参考图片) 第四步列出最短

qq_43063093的博客 1万+

safetymonitorapi

Summary of SA8653 Safety Monitor API Introduction This document details Safety Monitor APIs for the SA8653 QNNX platform, covering dual interfaces of APSS and SAIL. It defines core data structures and enumerations for subsystems, fault severity and health

qq_39257814的博客 1588

传教士与野人问题(完整状态搜索图)

传教士与野人问题 传教士和野人问题。三个传教士和三个野人在河的一岸, 有一条能载一个人或者两个 人的船。请设法使所有人都渡到河的另一岸, 要求在任何地方野人数都不能多于传教 士的人数。这个问题在AI 领域中很有名, 是因为它是第一个从分析的观点探讨问题。 对问题作如下抽象,以列表state=[c,a,b]分别代表初始岸边的传教士人数,野人人数,船只数目,有 初始状态:state=[3,3,1] agent所有可能行动: 当b==1时,在以下五种状态中选择一种执行, a=a-1,b=b-1,c=

南柯一梦的博客 3万+

内模控制(IMC)——理论、应用与实践

内模控制方法的核心思想是利用被控对象的数学模型(即内模)构建控制器,使得控制器可以“预知”被控系统的动态响应,从而在控制输入中提前补偿模型的固有特性和扰动影响。常见的内模控制结构中,将系统分为无延迟部分和扰动部分,并利用内部模型预测输出值,再通过反馈回路进行误差修正。utuimctufbtutui​mctuf​bt其中,uimctu_imc(t)ui​mct为内模预测得到的预补偿控制量,ufbtu_fb(t)uf​bt。

闲人编程的博客 2631

WorkBuddy CAD 审图救命课:约束、单位、尺寸链一次查清,打样前拦住返工

最危险的 CAD 文件不是打不开,而是看起来完整却混用了毫米与英寸、草图欠约束、关键尺寸没有来源。审图任务必须先列规则,再输出问题位置。 本课不会用“AI 一键完成”制造错觉,而是把 WorkBuddy、FreeCAD 0.21.2、OpenCascade 7.7 与人工审阅组成一条可复现链路。你会从“一份模拟 STEP 文件、参数表、装配基准与审图标准”出发,得到“单位报告、约束清单、尺寸链风险表与人工复核标记”,并学会用真实命令、错误信号和停止条件判断成果能不能进入下一阶段。

yueyeguzhuo的专栏 264

请教“修道士与野人问题”

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

colwater的专栏 2982

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

上一篇: 野人与修道士问题的Ruby实现
下一篇: 自己动手写操作系统(一) 作者:伊梅
dingx
博客等级 码龄24年 67粉丝 112原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值