100个python算法超详细讲解:农夫过河

2023-11-07

【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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

100个python算法超详细讲解:农夫过河 的相关文章

  • 如何在Python的SciPy中更改稀疏矩阵中的元素?

    我构建了一个小代码 我想用它来解决涉及大型稀疏矩阵的特征值问题 它工作正常 我现在要做的就是将稀疏矩阵中的一些元素设置为零 即最顶行中的元素 对应于实现边界条件 我可以调整下面的列向量 C0 C1 和 C2 来实现这一点 不过我想知道是否有
  • scipy 将一个稀疏矩阵的所有行附加到另一个稀疏矩阵

    我有一个 numpy 矩阵 想在其中附加另一个矩阵 这两个矩阵的形状为 m1 shape 2777 5902 m2 shape 695 5902 我想将 m2 附加到 m1 以便新矩阵的形状为 m new shape 3472 5902 当
  • 如何在 Windows 64 上安装 NumPy?

    NumPy 安装程序在注册表中找不到 python 路径 无法安装 需要 Python 2 5 版本 但在注册表中未找到该版本 OK 我必须修改注册表吗 我已经修改了 PATH 以指向Python25安装目录 我可以检查一下您使用的是什么安
  • 递归 lambda 表达式可能吗?

    我正在尝试编写一个调用自身的 lambda 表达式 但我似乎找不到任何语法 或者即使它是可能的 本质上我想将以下函数传输到以下 lambda 表达式中 我意识到这是一个愚蠢的应用程序 它只是添加 但我正在探索可以在 python 中使用 l
  • 用缺失的日期填充其他列 Nan Pandas DataFrame

    我实际上是从几个 Excel 文件中提取数据来监控我的每日卡路里摄入量 我设法使用列表理解来生成日期 我尝试使用合并或连接 但它不起作用 ValueError 您正在尝试合并对象和 float64 列 date list 2021 05 2
  • Kivy - 有所有颜色名称的列表吗?

    在 Kivy 中 小部件 color属性允许输入其值作为字符串颜色名称 也 例如在 kv file Label color red 是否有所有可能的颜色名称的列表 就在这里 来自Kivy 的文档 https kivy org doc sta
  • 结构差异 sudo() run('sudo 命令')

    我想知道函数之间有什么区别sudo 和函数run sudo u user smth 文档上有 sudo 在所有运行方式上都是相同的 除了它总是换行 调用 sudo 程序中的给定命令以提供超级用户 特权 但有几次 sudo cmd 提示我输入
  • 从扫描文档中提取行表 opencv python

    我想从扫描的表中提取信息并将其存储为 csv 现在我的表提取算法执行以下步骤 应用倾斜校正 应用高斯滤波器进行去噪 使用 Otsu 阈值进行二值化 进行形态学开局 Canny 边缘检测 进行霍夫变换以获得表格行 去除重复行 10像素范围内相
  • Django send_mail SMTPSenderRefused 530 与 gmail

    一段时间以来 我一直在尝试使用 Django 从我正在开发的网站接收电子邮件 现在 我还没有部署它 并且我正在使用Django开发服务器 我不知道这是否会影响它 这是我的 settings py 配置 EMAIL BACKEND djang
  • 在 Windows 上使用 apache mod_wsgi 运行 Flask 应用程序时导入冲突

    我允许您询问我在 Windows 上使用您的 mod wsgi portage 托管 Flask 应用程序时遇到的问题 我有两个烧瓶应用程序 由于导入冲突 只有一个可以同时存在 IE 如果请求申请 1 我有回复 然后 如果我请求应用程序 2
  • pytest:同一接口的不同实现的可重用测试

    想象一下我已经实现了一个名为的实用程序 可能是一个类 Bar在一个模块中foo 并为其编写了以下测试 测试 foo py from foo import Bar as Implementation from pytest import ma
  • 通过索引访问Python字典的元素

    考虑一个像这样的字典 mydict Apple American 16 Mexican 10 Chinese 5 Grapes Arabian 25 Indian 20 例如 我如何访问该字典的特定元素 例如 我想在对 Apple 的第一个
  • 如何在 pandas 中使用 read_fwf 跳过空行?

    I use pandas read fwf http pandas pydata org pandas docs stable generated pandas read fwf htmlPython pandas 0 19 2 中的函数读
  • 使用 Keras np_utils.to_categorical 的问题

    我正在尝试将整数的 one hot 向量数组制作为 keras 将能够使用的 one hot 向量数组来拟合我的模型 这是代码的相关部分 Y train np hstack np asarray dataframe output vecto
  • Python:IndexError:修改代码后列表索引超出范围

    我的代码应该提供以下格式的输出 我尝试修改代码 但我破坏了它 import pandas as pd from bs4 import BeautifulSoup as bs from selenium import webdriver im
  • Elasticsearch 通过搜索返回拼音标记

    我用语音分析插件 https www elastic co guide en elasticsearch plugins current analysis phonetic html由于语音转换 从弹性搜索中进行一些字符串匹配 我的问题是
  • 双击打开 ipython 笔记本

    相关文章 通过双击 osx 打开 ipython 笔记本 https stackoverflow com questions 16158893 open an ipython notebook via double click on osx
  • python 线程安全可变对象复制

    Is 蟒蛇的copy http docs python org 2 library copy html模块线程安全吗 如果不是 我应该如何在 python 中以线程安全的方式复制 deepcopy 可变对象 蟒蛇的GIL http en w
  • 查找总和为给定数字的值组合的函数

    这个帖子查找提供的 Sum 值的组合 https stackoverflow com a 20194023 1561176呈现函数subsets with sum 它在数组中查找总和等于给定值的值的组合 但由于这个帖子已经有6年多了 我发这
  • 如何为不同操作系统/Python 版本编译 Python C/C++ 扩展?

    我注意到一些成熟的Python库已经为大多数架构 Win32 Win amd64 MacOS 和Python版本提供了预编译版本 针对不同环境交叉编译扩展的标准方法是什么 葡萄酒 虚拟机 众包 我们使用虚拟机和Hudson http hud

随机推荐

  • BME/BMP280环境传感器、MLX90614红外测温传感器、HX711称重模块

    Mixly 是由北师大米思齐团队开发的图形化编程软件 自发布以来深受国内创客圈的喜爱 Mixly 编程软件采用图形化编程 不用记代码 只需要拖拽 简单设置 就能让你快速完成创意电子编程 本专栏系列课程由裘炯涛老师主讲 从基础入门到逐步提升
  • 数字货币即将面世 蹭“数字货币”热度套路频现

    随着央行数字人民币逐步在北京 上海等地进入测试阶段 数字货币在我国呼之欲出 与此同时 相关谣言或虚假信息也层出不穷 蹭 数字货币 热度的常见套路都有哪些 一起来看看 在网上签到学习就能提现 近日 某非法平台宣称 该平台系国家为大力发展数字货
  • 循序渐进,学会用pyecharts绘制玫瑰图

    循序渐进 学会用pyecharts绘制玫瑰图 玫瑰图简介 玫瑰图全称南丁格尔玫瑰图 是英国护士和统计学家弗罗伦斯 南丁格尔发明的 又名为极区图 南丁格尔自己常昵称这类图为鸡冠花图 coxcomb 用以表达军医院季节性的死亡率 提供给那些不太
  • adb install 多个设备时指定设备

    在emulator 5554模拟器上安装ebook apk adb s emulator 5554 install ebook apk 在真机上安装ebook apk adb s HT9BYL904399 install ebook apk
  • 可孚医疗:「最懂互联网」的医疗器械企业是如何炼成的?

    如果说钉钉在过去的标签是软件 是低代码 那么在医疗这个赛道里 这些标签已经不足以成为钉钉价值的侧写 除了固有标签之外 在可孚医疗的场景里 钉钉可以连接 可以成为智能BI 也更可以做到内外部协同等 作者 皮爷 出品 产业家 1000分 打开可
  • GetX项目级实战

    在使用了 Provider 一年后 遇到了很多阻力 期间尝试过 BLoC MobX 均不如意 一个样本代码太多 使用复杂 一个生产代码要等很久 难道 Flutter 就没有诸如原生 Android 的 jetpack 套装一样方便的套件吗
  • Cyclic Components CodeForces - 977E(找简单环)

    先求连通块 再看是不是所有连通块的点的度数为2 如果是那就是简单环 只不过我觉得我这个代码时间复杂度还是挺高的 虽然这题没啥问题 不过我看有他人是一遍用dfs找环 一遍判断找到环时的那个点的度数是不是2 AC代码 include
  • ES:一次分片设计问题导致的故障

    现象 1 单节点CPU持续高 2 写入骤降 3 线程池队列积压 但没有reject 4 使用方没有记录日志 排查 1 ES监控 只能看到相应的结果指标 无法反应出原因 2 ES日志 大量日志打印相关异常 routate等调用栈 core a
  • Java是解释型还是编译型语言?

    Java是解释型还是编译型语言 首先JVM是什么 JVM虚拟机也是java的运行环境 因为所有系统平台都支持JVM 所以实现了Java的跨平台 我们可以把JVM虚拟机比作人 有食物供我们食用 当我们需要吃哪种食物的时候就吃哪个实物 在JVM
  • 深度学习笔记(五) 代价函数的梯度求解过程和方法

    作为自己的笔记系列 方便自己查阅和理解 1 什么是梯度 梯度 本意是一个向量 矢量 当某一函数在某点处沿着该方向的方向导数取得该点处的最大值 即函数在该点处沿方向变化最快 变化率最大 为该梯度的模 在二元函数的情形 设函数z f x y 在
  • Linux C中对json格式数组数据的生成与解析

    在网络通信中 数据经常被做成json格式的来进行传输 那么我们怎么在linux系统中去做json格式的数据呢 怎么将接收到的json格式的数据解析出来呢 1 linux json库的安装 1 下载json c源码包 2 解压json c的源
  • Android Studio NDK开发注意

    1 如果JNILibs armeabi中有相应的库文件 编绎重新生成的 so文件不会打包到新的apk中
  • 干掉 “重复代码” 的技巧有哪些?

    软件工程师和码农最大的区别就是平时写代码时习惯问题 码农很喜欢写重复代码而软件工程师会利用各种技巧去干掉重复的冗余代码 业务同学抱怨业务开发没有技术含量 用不到设计模式 Java 高级特性 OOP 平时写代码都在堆 CRUD 个人成长无从谈
  • UDP包传送字符串实现方法以及方格乱码的出现原因和解决办法

    在使用socket发送udp包传输文本时 由于包中的char型数组是定长的 且其长度大于消息长度 所以其中必有很多空元素 当接收端接收到udp包时进行转码 空元素就会被转码成方块形状的乱码 解决办法 每条消息发送完毕后添加 作为记号 接收后
  • 浏览器渲染机制 (二)浏览器主进程-浏览器内核-浏览器渲染流程

    文章目录 浏览器主进程和浏览器渲染进程的通信过程 浏览器内核 渲染进程 中线程之间的管理 GUI渲染线程与JS引擎线程互斥 JS阻塞页面加载 WebWorker JS的多线程 WebWorker与SharedWorker 总结浏览器渲染流程
  • adb通过网络连接

    1 使用USB数据线连接设备 2 在命令行输入adb tcpip 5555 5555为端口号 可以自由指定 3 断开 USB数据 此时可以连接你需要连接的 USB设备 4 再计算机命令行输入 adb connect lt 设备的IP地址 g
  • 自动计算30天内的股价最高价源代码

    我可以回答这个问题 您可以使用以下代码来计算30天内股价的最高价 复制 import pandas as pd import yfinance as yf 设置股票代码和日期范围 symbol AAPL start date 2021 01
  • Python绝技:运用Python成为顶级黑客

    Python 是一门常用的编程语言 它不仅上手容易 而且还拥有丰富的支持库 对经常需要针对自己所 处的特定场景 以极少的代码量实现所需的功能 Python绝技 运用Python成为顶级黑客结合具体的场景和真 实的案例 详述了 Python
  • 《软件测试的艺术》第三章 代码检查、走查和评审

    软件测试的艺术 第三章 代码检查 走查和评审 3 1 代码检查与走查 3 2 代码检查 3 2 1 代码检查小组 3 2 2 检查议程与注意事项 3 2 3 对事不对人 和人有关的注意事项 3 2 4 代码检查的衍生功效 3 3 用于代码检
  • 100个python算法超详细讲解:农夫过河

    100个python算法超详细讲解 谷哥技术 1 问题描述 一个农夫在河边带了一匹狼 一只羊和一棵白菜 他需要把这三样东西用 船带到河的对岸 然而 这艘船只能容下农夫本人和另外一样东西 如果农夫 不在场的话 狼会吃掉羊 羊也会吃掉白菜 请编