Python基于回溯法子集树模板解决野人与传教士问题示例


Posted in Python onSeptember 11, 2017

本文实例讲述了Python基于回溯法子集树模板解决野人与传教士问题。分享给大家供大家参考,具体如下:

问题

在河的左岸有N个传教士、N个野人和一条船,传教士们想用这条船把所有人都运过河去,但有以下条件限制:

(1)修道士和野人都会划船,但船每次最多只能运M个人;
(2)在任何岸边以及船上,野人数目都不能超过修道士,否则修道士会被野人吃掉。

假定野人会服从任何一种过河安排,请规划出一个确保修道士安全过河的计划。

分析

百度一下,网上全是用左岸的传教士和野人人数以及船的位置这样一个三元组作为状态,进行考虑,千篇一律。

我换了一种考虑,只考虑船的状态。

船的状态:(x, y) x表示船上x个传教士,y表示船上y个野人,其中 |x|∈[0, m], |y|∈[0, m], 0<|x|+|y|<=m, x*y>=0, |x|>=|y|

船从左到右时,x,y取非负数。船从右到左时,x,y取非正数

解的编码:[(x0,y0), (x1,y1), ..., (xp,yp)] 其中x0+x1+...+xp=N, y0+y1+...+yp=N

解的长度不固定,但一定为奇数

开始时左岸(N, N), 右岸(0, 0)。最终时左岸(0, 0), 右岸(N, N)

由于船的合法状态是动态的、二维的。因此,使用一个函数get_states()来专门生成其状态空间,使得主程序更加清晰。

代码

n = 3 # n个传教士、n个野人
m = 2 # 船能载m人
x = [] # 一个解,就是船的一系列状态
X = [] # 一组解
is_found = False # 全局终止标志
# 计算船的合法状态空间(二维)
def get_states(k): # 船准备跑第k趟
  global n, m, x
  if k%2==0: # 从左到右,只考虑原左岸人数
    s1, s2 = n - sum(s[0] for s in x), n - sum(s[1] for s in x)
  else:    # 从右到左,只考虑原右岸人数(将船的历史状态累加可得!!!)
    s1, s2 = sum(s[0] for s in x), sum(s[1] for s in x)
  for i in range(s1 + 1):
    for j in range(s2 + 1):
      if 0 < i+j <= m and (i*j == 0 or i >= j):
        yield [(-i,-j), (i,j)][k%2==0]  # 生成船的合法状态
# 冲突检测
def conflict(k): # 船开始跑第k趟
  global n, m, x
  # 若船上载的人与上一趟一样(会陷入死循环!!!!)
  if k > 0 and x[-1][0] == -x[-2][0] and x[-1][1] == -x[-2][1]:
    return True
  # 任何时候,船上传教士人数少于野人,或者无人,或者超载(计算船的合法状态空间时已经考虑到了。)
  #if 0 < abs(x[-1][0]) < abs(x[-1][1]) or x[-1] == (0, 0) or abs(sum(x[-1])) > m:
  #  return True
  # 任何时候,左岸传教士人数少于野人
  if 0 < n - sum(s[0] for s in x) < n - sum(s[1] for s in x):
    return True
  # 任何时候,右岸传教士人数少于野人
  if 0 < sum(s[0] for s in x) < sum(s[1] for s in x):
    return True
  return False # 无冲突
# 回溯法
def backtrack(k): # 船准备跑第k趟
  global n, m, x, is_found
  if is_found: return # 终止所有递归
  if n - sum(s[0] for s in x) == 0 and n - sum(s[1] for s in x) == 0: # 左岸人数全为0
    print(x)
    is_found = True
  else:
    for state in get_states(k): # 遍历船的合法状态空间
      x.append(state)
      if not conflict(k):
        backtrack(k+1) # 深度优先
      x.pop()  # 回溯
# 测试
backtrack(0)

效果图

Python基于回溯法子集树模板解决野人与传教士问题示例

解的解释,从上往下看:

Python基于回溯法子集树模板解决野人与传教士问题示例

一个结论

貌似只有满足m = n-1,此问题才有解

更多关于Python相关内容可查看本站专题:《Python数据结构与算法教程》、《Python Socket编程技巧总结》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
Python面向对象类的继承实例详解
Jun 27 Python
python opencv实现旋转矩形框裁减功能
Jul 25 Python
python自动化生成IOS的图标
Nov 13 Python
python代码 输入数字使其反向输出的方法
Dec 22 Python
Python多进程写入同一文件的方法
Jan 14 Python
解决nohup执行python程序log文件写入不及时的问题
Jan 14 Python
python实现通过flask和前端进行数据收发
Aug 22 Python
python 字典访问的三种方法小结
Dec 05 Python
Python实现bilibili时间长度查询的示例代码
Jan 14 Python
如何使用Python调整图像大小
Sep 26 Python
python request 模块详细介绍
Nov 10 Python
Pytest测试框架基本使用方法详解
Nov 25 Python
Python 高级专用类方法的实例详解
Sep 11 #Python
Python 异常处理的实例详解
Sep 11 #Python
Python基于回溯法子集树模板解决马踏棋盘问题示例
Sep 11 #Python
Python基于回溯法子集树模板解决找零问题示例
Sep 11 #Python
详解 Python 与文件对象共事的实例
Sep 11 #Python
Python 私有函数的实例详解
Sep 11 #Python
Python模拟用户登录验证
Sep 11 #Python
You might like
PHP以指定字段为索引返回数据库所取的数据数组
2013/06/30 PHP
thinkphp的静态缓存用法分析
2014/11/29 PHP
PHP实现的简单mock json脚本分享
2015/02/10 PHP
详细对比php中类继承和接口继承
2018/10/11 PHP
PHP+百度AI OCR文字识别实现了图片的文字识别功能
2019/05/08 PHP
JavaScript DOM学习第六章 表单实例
2010/02/19 Javascript
修复ie8&amp;chrome下window的resize事件多次执行
2011/10/20 Javascript
Javascript/Jquery——简单定时器的多种实现方法
2013/07/03 Javascript
利用毫秒减值计算时长的js代码
2013/09/22 Javascript
javascript动态添加、修改、删除对象的属性与方法详解
2014/01/27 Javascript
js实现网页图片延时加载 提升网页打开速度
2016/01/26 Javascript
JS/jQ实现免费获取手机验证码倒计时效果
2016/06/13 Javascript
vue制作加载更多功能的正确打开方式
2016/10/12 Javascript
如何利用@angular/cli V6.0直接开发PWA应用详解
2018/05/06 Javascript
浅析vue给不同环境配置不同打包命令
2018/08/17 Javascript
JavaScript数据结构与算法之检索算法示例【二分查找法、计算重复次数】
2019/02/22 Javascript
vue增加强缓存和版本号的实现方法
2019/05/01 Javascript
js常见遍历操作小结
2019/06/06 Javascript
JavaScript中BOM对象原理与用法分析
2019/07/09 Javascript
vue实现点击按钮下载文件功能
2019/10/11 Javascript
vue 使用 vue-pdf 实现pdf在线预览的示例代码
2020/04/26 Javascript
jQuery实现放大镜案例
2020/10/19 jQuery
js实现磁性吸附的示例
2020/10/26 Javascript
node使用async_hooks模块进行请求追踪
2021/01/28 Javascript
Python随机生成数模块random使用实例
2015/04/13 Python
python中如何使用正则表达式的集合字符示例
2017/10/09 Python
python 字符串和整数的转换方法
2018/06/25 Python
python按修改时间顺序排列文件的实例代码
2019/07/25 Python
Python使用Beautiful Soup爬取豆瓣音乐排行榜过程解析
2019/08/15 Python
美国中小型企业领先的办公家具供应商:Office Designs
2016/11/26 全球购物
领导班子四风表现材料
2014/08/23 职场文书
党政领导班子四风问题对照检查材料思想汇报
2014/10/02 职场文书
工作态度不端正检讨书
2014/10/04 职场文书
护士求职自荐信
2015/03/25 职场文书
PHP中多字节字符串操作实例详解
2021/08/23 PHP
解决redis批量删除key值的问题
2022/03/23 Redis