过河问题(牛虎过河、商人仆人过河、农夫妖怪过河、传教士野人过河)(第2届第2题)

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

最新链接


题目要求

        问题描述:三只牛三只虎过河,船最多只能容纳两只动物,且船在往返途中不能为空。在任一岸边,若牛的数量少于虎的数量,则牛就会被吃掉。为了使动物全部过河且使动物无损失,请制定合理的渡河方案。


解决方案

        这也是一个经典的渡河问题了,由此衍化出的版本有商人仆人(随从)过河,农夫妖怪过河,传教士野人过河...除了角色有变化,内容本质上是一样的。

        假设原来的动物和船都在A岸,现在想渡河到对面的B岸。考虑牛虎数量和船的位置,可以将本题中的所有可能出现的情形描述为静态属性动态属性。静态属性就是船停靠在A岸或者B岸时,A岸牛、虎的数量(A岸数目一定时,B岸也一定,所以只需考虑一边就行),动态属性就是船在运行中,A按或者B岸牛、虎的数量。

        进一步考虑,只要知道了相邻的两个静态属性,也就知道了发生在其中的动态属性。比如开始船在A岸,A岸有牛、虎各3只,下一个状态为船在B岸,A岸有牛虎各两只,那它们之间的动态属性一定是船由A到B,且运送了一牛一虎过去。所以在这里,我们只需要确定每一步对应的静态属性,在编程中,将其描述为状态。对于岸边的牛或者虎的数量,只有0到3这4个取值,对于船的停靠位置,只有A岸和B岸两种情形,这样一来,就有了4*4*2=32种状态。在这32种状态中,有些状态会引起牛吃虎,这必须被排除掉。

        到这里,制定渡河方案的问题就转换为在这32个状态中探寻合理“状态路径”的问题。我们从初始状态——A岸牛虎各3只,船在A岸这个状态出发,不断判断遇到的下一个状态是否合理。如果下一个状态合理,就将其加入到“状态路径”当中,并留下访问标记(防止重复添加,形成环路),否则,跳过此状态。在不断向前探寻的过程中,如果遇到一个标记为已访问的状态,说明该状态已加入路径,需要探寻下一种可能。如果遇到了结束状态——A岸牛虎为0,船在B岸,则说明找到了一条完整的状态路径”,这时需要打印这条路径,并清除当前状态的访问标记,并退出上一个状态,继续寻找下一种可能性。

        在具体编程中,可以利用来存储初始状态到结束状态的所有状态,目的是为了在遇到不符合题意的状态时,可以原路返回,便于回溯。由于在推进过程中,每个状态都是基于对岸边牛虎数量和船的停靠位置的判断,所以,考虑用递归会更容易。但值得注意的是,这里的递归并不像斐波那契数列那样不断衍生出先决条件,而是更类似于“尾递归”,即递归的外壳迭代的内心

        戳这☛:尾递归=递归+迭代?


源码示例



结果展示



小结

        一个经典的过河问题,本质就是在各状态之间寻求符合题意的状态路径,在有多条路径的情形下,需要使用栈保存之前的各个状态,以便在遇到不符合条件的状态时可以回溯。这种回溯思想在迷宫寻路问题和八皇后问题中都有体现。可以说是一母同胞,属于同一类型的问题。


▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值