【100个python算法超详细讲解】@谷哥技术

1.问题描述
一个农夫在河边带了一匹狼、一只羊和一棵白菜,他需要把这三样东西用
船带到河的对岸。然而,这艘船只能容下农夫本人和另外一样东西。如果农夫
不在场的话,狼会吃掉羊,羊也会吃掉白菜。请编程为农夫解决这个过河问
题。
2.问题分析
根据问题描述可知,该问题涉及的对象较多,而且运算步骤也较为复杂,
因此在使用Python语言实现时,首先需要将具体问题数字化。
由于整个过程的实现需要多步,而不同步骤中各个事物所处的位置不同,
因此可以定义一个二维数组(嵌套列表)来表示4个对象——狼(wolf)、羊
(goat)、白菜(cabbage)和农夫(farmer)。对于东岸和西岸,可以用east和
west表示,也可以用0和1来表示,以保证程序设计时的简便性。
题目要求给出农夫、狼、羊和白菜的过河步骤,没有对先后顺序进行约
束,这就需要给各个事物依次进行编号,然后依次试探,若试探成功,再进行
下一步试探。因此,解决该问题可以使用循环或者递归算法,以避免随机盲目
运算而且保证每种情况都可以试探到。
题目要求求出农夫带一只羊、一匹狼和一棵白菜过河的所有办法,所以依
次成功返回运算结果后,需要继续运算,直至求出所有结果,即给出农夫不同
的过河方案。
3.算法设计
本程序使用递归算法,为了方便将各个实例数字化,定义二维数组int a[N]
[4]存储每一步中各个事物所处的位置。二维数组的一维下标表示当前进行的步
骤,第二维下标可能的取值为0~3,在这里规定它与4种事物的具体对应关系
为:0——狼、1——羊、2——白菜、3——农夫。接着再将东岸和西岸数字
化,用0表示东岸,1表示西岸,该信息存储在二维数组的对应元素中。
初始情况下,当前步骤为0,此时狼、羊、白菜和农夫都在东岸,则使用a
数组来表示该状态为:

假设在第3步之后狼在东岸,羊在西岸,白菜在东岸,农夫在西岸,则该
步骤的存储状态为:

定义Step变量表示渡河的步骤,则成功渡河之后,a数组中的存储状态为:

因为成功渡河后,狼、羊、白菜和农夫都在河的西岸,因此有a[Step]
[0]+a[Step][1]+a[Step][2]+a[Step][3]=4。
题目中要求狼和羊、羊和白菜不能在一起,因此若有下述情况出现,则发
生错误,应返回操作。
a[Step][1]!=a[Step][3] and (a[Step][2]==a[Step][1] or a[Step][0]==a[Step][1])
程序采用递归算法,主程序结构如图8.3所示。

在程序实现时,除了定义a数组来存储每一步中各个对象所处的位置以
外,再定义一维数组b[N]来存储每一步中农夫是如何过河的。
程序中实现递归操作部分的核心代码为:

# 递归,从带第一种对象开始依次向下循环,同时限定递归的界限
for i in range(-1, 3):
b[Step] = i # 记录农夫渡河方式
a[Step+1] = a[Step][:] # 复制上一步状态,进行下一步移动
# 农夫过去或者回来
a[Step + 1][3] = 1 - a[Step + 1][3]
if i == -1:
search(Step + 1) # 进行第一步
elif a[Step][i] == a[Step][3]: # 若该物与农夫同岸,带回
a[Step + 1][i] = a[Step + 1][3] # 带回该物
search(Step + 1) # 进行下一步

每次循环从-1到2依次代表农夫渡河时为一人、带狼、带羊、带白菜通过,
利用语句“b[Step]=i”分别记录每一步中农夫的渡河方式,语句“a[Step+1]
[i]=a[Step+1][3]”是利用赋值方式使该对象与农夫一同到对岸或者回到本岸。若
渡河成功,则依次输出渡河方式。“i<3”为递归操作的界限,若i=2时仍无符合
条件的方式,则渡河失败。
在递归的过程中每进行一步都需要判断条件以决定是否继续进行此次操
作,具体的判断代码为:

# 若该步骤能使各值均为1,则输出结果,进入回归步骤
if a[Step][0] + a[Step][1] + a[Step][2] + a[Step][3] == 4:
……
return

上面的的代码表示若当前步骤能使各值均为1,则渡河成功,输出结果,
进入回归步骤。
若当前步骤与以前的步骤相同,则返回操作,代码如下:

for i in range(Step):
if a[i] == a[Step]: # 若该步与以前步骤相同,则返回操作
return

若羊和农夫不在一块而狼和羊或者羊和白菜在一块,则返回操作,判断代
码如下:

若羊和农夫不在 起而狼和羊或者羊和白菜在 起 则返回操作
# 若羊和农夫不在一起而狼和羊或者羊和白菜在一起,则返回操作
if a[Step][1] != a[Step][3] and (a[Step][2] == a[Step][1] or a[Step][0] == a[Step][1]):
return

递归部分程序结构如图8.4所示。

4.完整的程序

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @author : liuhefei
# @desc: 农夫过河
def search(Step):
# 若该步骤能使各值均为1,则输出结果,进入回归步骤
if a[Step][0] + a[Step][1] + a[Step][2] + a[Step][3] == 4:
for i in range(Step + 1): # 能够依次输出不同的方案
print('east:', end=' ')
if a[i][0] == 0:
print('wolf', end=' ')
if a[i][1] == 0:
print('goat', end=' ')
if a[i][2] == 0:
print('cabbage', end=' ')
if a[i][3] == 0:
print('farmer', end=' ')
if a[i][0] and a[i][1] and a[i][2] and a[i][3]:
print("none", end='')
print(end=' ')
print('west:', end=' ')
if a[i][0] == 1:
print("wolf", end=' ')
if a[i][1] == 1:
print('goat', end=' ')
if a[i][2] == 1:
print('cabbage', end=' ')
if a[i][3] == 1:
print('farmer', end=' ')
if not (a[i][0] or a[i][1] or a[i][2] or a[i][3]):
print('none', end='')
print('\n')
if i < Step:
print(' the %d time' % (i + 1))
if i>0 and i<Step:
if a[i][3] == 0: # 农夫在本岸
print(" -----> farmer ", end='')
print(name[b[i] + 1])
else: # 农夫在对岸
print(" <----- farmer ", end='')
print(name[b[i] + 1])
print('\n\n\n')
return
for i in range(Step):
if a[i] == a[Step]: # 若该步与以前的步骤相同,取消操作
return
# 若羊和农夫不在一起而狼和羊或者羊和白菜在一起,则取消操作
if a[Step][1] != a[Step][3] and (a[Step][2] == a[Step][1] or a[Step][0] == a[Step][1]):
return
# 递归,从带第一种对象开始依次向下循环,同时限定递归的界限
for i in range(-1, 3):
b[Step] = i # 记录农夫渡河的方式
a[Step+1] = a[Step][:] # 复制上一步的状态,进行下一步移动
a[Step + 1][3] = 1 - a[Step + 1][3] # 农夫过去或者回来
if i == -1:
search(Step + 1) # 进行第一步
elif a[Step][i] == a[Step][3]: # 若该物与农夫同岸,带回
a[Step + 1][i] = a[Step + 1][3] # 带回该物
search(Step + 1) # 进行下一步
if __name__ == '__main__':
N = 15
a = [[0] * 4 for i in range(N)]
b = [0] * N
name = [" ",
"and wolf",
"and goat",
"and cabbage"]
print(' 农夫过河问题,解决方案如下:\n')
search(0)

5.运行结果
在Pycharm下运行程序,结果如下:

E:\code\python\Interest-python\venv\Scripts\python.exe E:/code/python/
农夫过河问题,解决方案如下:
east: wolf goat cabbage farmer west: none
the 1 time
east: wolf cabbage west: goat farmer
the 2 time
<----- farmer
east: wolf cabbage farmer west: goat
the 3 time
-----> farmer and wolf
east: cabbage west: wolf goat farmer
the 4 time
<----- farmer and goat
east: goat cabbage farmer west: wolf
the 5 time
-----> farmer and cabbage
east: goat west: wolf cabbage farmer
the 6 time
<----- farmer
east: goat farmer west: wolf cabbage
the 7 time
-----> farmer and goat
east: none west: wolf goat cabbage farmer
east: wolf goat cabbage farmer west: none
the 1 time
east: wolf cabbage west: goat farmer
the 2 time
<----- farmer
east: wolf cabbage farmer west: goat
the 3 time
-----> farmer and cabbage
east: wolf west: goat cabbage farmer
the 4 time
<----- farmer and goat
east: wolf goat farmer west: cabbage
the 5 time
-----> farmer and wolf
east: goat west: wolf cabbage farmer
the 6 time
<----- farmer
east: goat farmer west: wolf cabbage
the 7 time
-----> farmer and goat
east: none west: wolf goat cabbage farmer

100个python算法超详细讲解:农夫过河相关推荐

  1. 100个python算法超详细讲解:搬山游戏

    [100个python算法超详细讲解]@谷歌学术 1.问题描述 设有n座山,计算机与人作为比赛的双方,轮流搬山.规定每次搬 山数不能超过k座,谁搬最后一座谁输.游戏开始时,计算机请人输入 山的总数n和 ...

  2. 100个python算法超详细讲解:平分7筐鱼

    [100个python算法超详细讲解]@谷哥技术 1.问题描述 2.乙.丙三位渔夫出海打鱼,他们随船带了21只箩筐.当晚返航时, 他们发现有7筐装满了鱼,还有7筐装了半筐鱼,另外7筐是空的,由于他们 ...

  3. 100个python算法超详细讲解:邮票组合

    [100个python算法超详细讲解]@谷哥技术 1.问题描述 我们寄信都要贴邮票,在邮局有一些小面值的邮票,通过这些小 面值邮票中的一张或几张的组合,可以满足不同邮件的不同邮资.现 在,邮局有4种不 ...

  4. 100个python算法超详细讲解:递归解决年龄问题

    [100个python算法超详细讲解]@谷哥技术 1.问题描述 有5个人坐在一起,问第5个人多少岁,他说比第4个人大2岁.问 第4个人多少岁,他说比第3个人大2岁.问第3人多少岁,他说比第2个 人大2 ...

  5. 100个python算法超详细讲解:谁是窃贼

    [100个python算法超详细讲解]@谷哥技术 1.问题描述 警察审问4名窃贼嫌疑犯.现在已知,这4人当中仅有一名是窃 贼,还知道这4个人中的每个人要么是诚实的,要么总是说谎. 下面是这4个人给警察 ...

  6. 100个python算法超详细讲解:抢30游戏

    [100个python算法超详细讲解]@谷歌学术 1.问题描述 由两个人玩"抢30"游戏,游戏规则是:第一个人先说"1"或"1,2",第 二 ...

  7. 100个python算法超详细讲解:卡布列克常数

    [100个python算法超详细讲解]@谷哥技术 1.问题描述 对于任意一个4位数n,进行如下的运算: 1)将组成该4位数的4个数字由大到小排列,形成由这4个数字构 成的最大的4位数. 2)将组成该4 ...

  8. 100个python算法超详细讲解:孪生素数

    [100个python算法超详细讲解@谷哥技术] 1.问题描述 本节要研究孪生素数的问题,先来看看什么是孪生素数. 所谓孪生素数指的是间隔为2的两个相邻素数,因为它们之间的距离已经 近得不能再近了,如 ...

  9. 100个python算法超详细讲解:狼追兔子

    [100个python算法超详细讲解]@谷哥技术 1.问题描述 一只兔子躲进了10个环形分布的洞中的某一个.狼在第一个洞中 没有找到兔子,就隔一个洞,到第三个洞中去找:如果没有找到,就 隔两个洞,到第 ...

  10. 100个python算法超详细讲解:猴子吃桃

    [100个python算法超详细讲解]@谷哥技术 1.问题描述 一个猴子摘了一些桃子,它第一天吃掉了其中的一半然后再多吃了 一个,第二天照此方法又吃掉了剩下桃子的一半加一个,以后每天如 此,直到第十天 ...

最新文章

  1. 一文看懂机器学习中的常用损失函数
  2. ASP.NET MVC: EF 没有创建数据库表
  3. 每天一道LeetCode-----将有序序列转成高度平衡二叉搜索树
  4. c++-内存管理-G2.9
  5. 容器源码解析之LinkedHashSet(六)
  6. c/c++ code JSON
  7. 测试:脱离VS2010使用自动化测试时出现 6DA215C2-D80D-42F2-A514-B44A16DCBAAA 错误
  8. docker安装redis并将配置文件和数据文件映射到外部
  9. 网络协议从入门到底层原理(5)传输层(UDP、TCP - 可靠传输、流量控制、拥塞控制、建立连接、释放连接)
  10. 无线射频收发芯片SI24R1技术相关问题解答
  11. wordpress后台固定菜单消失不见了怎么办?
  12. pandas学习-中期测试
  13. 三十岁it人的一些经历
  14. 关于LCD_ShowString的顽固感叹号!
  15. SWF文件格式详解(1)
  16. win10 Edge浏览器 触控板 快捷键
  17. 学习数学建模算法与应用【数据预处理】
  18. 【练习题】python集合练习
  19. #BDA#笔记#业务知识:常见行业业务模式指标6零售行业
  20. Django 序列化和反序列化(九)

热门文章

  1. 程序在单片机里是如何运行的?
  2. python爬虫之通用爬虫和聚焦爬虫
  3. Portraiture4.0最新免费磨皮美白滤镜修图插件
  4. 计网笔记-计网总结-计网复习提纲-第一章.概述
  5. It seems like the kubelet isn‘t running or healthy
  6. TriangleCount三角形计数
  7. codeblock-(no debugging symbols found)(已解决)
  8. 文本框失去焦点事件、获得焦点事件
  9. idea从零到精通目录导航
  10. 基于java SSM框架的医院体检管理系统