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之入门(二)基本数据类型
May 25 Python
python实现读取并显示图片的两种方法
Jan 13 Python
Python入门之三角函数全解【收藏】
Nov 08 Python
matplotlib实现区域颜色填充
Mar 18 Python
Python3.8对可迭代解包的改进及用法详解
Oct 15 Python
布隆过滤器的概述及Python实现方法
Dec 08 Python
Python底层封装实现方法详解
Jan 22 Python
Python xlrd excel文件操作代码实例
Mar 10 Python
Python爬虫爬取杭州24时温度并展示操作示例
Mar 27 Python
python神经网络编程实现手写数字识别
May 27 Python
基于K.image_data_format() == 'channels_first' 的理解
Jun 29 Python
分享提高 Python 代码的可读性的技巧
Mar 03 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
咖啡磨器 如何选购一台适合家用的意式磨豆机
2021/03/05 新手入门
jQuery学习笔记之Helloworld
2010/12/22 Javascript
基于JQuery的Select选择框的华丽变身
2011/08/23 Javascript
jquery实现通用版鼠标经过淡入淡出效果
2014/06/15 Javascript
整理Javascript基础入门学习笔记
2015/11/29 Javascript
AngularJS实现全选反选功能
2015/12/08 Javascript
jQuery判断元素是否显示 是否隐藏的简单实现代码
2016/05/19 Javascript
JavaScript判断数字是否为质数的方法汇总
2016/06/02 Javascript
AngularJS ng-change 指令的详解及简单实例
2016/07/30 Javascript
AngularJS教程之环境设置
2016/08/16 Javascript
node.js爬虫爬取拉勾网职位信息
2017/03/14 Javascript
js时间查询插件使用详解
2017/04/07 Javascript
微信小程序日历组件calendar详解及实例
2017/06/08 Javascript
label+input实现按钮开关切换效果的实例
2017/08/16 Javascript
Bootstrap框架建立树形菜单(Tree)的实例代码
2017/10/30 Javascript
webpack实现一个行内样式px转vw的loader示例
2018/09/13 Javascript
微信小程序获取用户信息并保存登录状态详解
2019/05/10 Javascript
详解vuex之store源码简单解析
2019/06/13 Javascript
js判断在哪个浏览器打开项目的方法
2020/01/21 Javascript
原生JS实现无缝轮播图片
2020/06/24 Javascript
Node.js 中判断一个文件是否存在
2020/08/24 Javascript
[36:05]完美世界DOTA2联赛循环赛 Forest vs DM 第一场 11.06
2020/11/06 DOTA
[41:17]完美世界DOTA2联赛PWL S3 access vs CPG 第二场 12.13
2020/12/17 DOTA
Python的Flask框架中Flask-Admin库的简单入门指引
2015/04/07 Python
python获取当前时间对应unix时间戳的方法
2015/05/15 Python
flask框架渲染Jinja模板与传入模板变量操作详解
2020/01/25 Python
Windows下Anaconda和PyCharm的安装与使用详解
2020/04/23 Python
VSCode配合pipenv搞定虚拟环境的实现方法
2020/05/17 Python
深入解析HTML5的IndexedDB索引数据库
2015/09/14 HTML / CSS
英国玛莎百货美国官网:Marks & Spencer美国
2018/11/06 全球购物
接口中的方法可以是abstract的吗
2015/07/23 面试题
主题婚礼策划方案
2014/02/10 职场文书
求职简历自我评价范例
2014/03/12 职场文书
党支部2014年度工作总结
2014/12/04 职场文书
前端学习——JavaScript原生实现购物车案例
2021/03/31 Javascript
Python多个MP4合成视频的实现方法
2021/07/16 Python