传教士与野人过河问题

代码模块参考文章:传教士与野人过河问题(numpy、pandas)_python过河问题_醉蕤的博客-CSDN博客

问题描述

一般的传教士和野人问题(Missionaries and  Cannibals):有N个传教士和C个野人来到河边准 备渡河。河岸有一条船,每次至多可供K人乘渡。 问传教士为了安全起见,应如何规划摆渡方案,使 得任何时刻,在河的两岸以及船上的野人数目总是 不超过传教士的数目,但允许在河的某一岸只有野 人而没有传教士。

这里讨论基于N=3,C=3,k=2

状态表示:(m,w,B);初始状态: (3, 3, 1);目标状态: (0,0,0)

启发性规则

操作符(产生式规则)
左岸往右岸运载产生式
L10  if(M,W,1) then (M-1,W,0)     (左往右运1传教士)
L01  if(M,W,1) then (M,W-1,0)     (左往右运1野人)
L11  if(M,W,1) then (M-1,W-1,0)  (左往右运1传教士和1野人)
L20  if(M,W,1) then (M-2,W,0)     (左往右运2传教士)
L02  if(M,W,1) then (M,W-2,0)     (左往右运2野人)

右岸往左岸运载产生式
R10  if(M,W,0) then (M+1,W,1)    (右往左运1传教士)
R01  if(M,W,0) then (M,W+1,1)    (右往左运1野人)
R11  if(M,W,0) then (M+1,W+1,1) (右往左运1传教士和1野人)
R20  if(M,W,0) then (M+2,W,1)    (右往左运2传教士)
R02  if(M,W,0) then (M,W+2,1)    (右往左运2野人)

路径方案展示

总共有四种解决方案

实现代码(含具体解释)

import numpy as npM = int(input("请输入传教士的数量:"))  # 传教士数量
C = int(input("请输入野人的数量:"))  # 野人数量
K = int(input("请输入船的最大容量:"))  # 船的最大容量child = []  # child:用于存储所有扩展节点
open_list = []  # open list
closed_list = []  # closed listclass State:def __init__(self, m, c, b):self.m = m  # 左岸传教士的数量self.c = c  # 左岸野人的数量self.b = b  # b为1时船在左岸;b为0时船在右岸self.g = 0  # 该结点所在的层级self.f = 0  # 该结点的启发性层度f = g + h# father这个属性是Stateself.father = Noneself.node = np.array([m, c, b])init = State(M, C, 1)  # 初始节点
goal = State(0, 0, 0)  # 目标节点# 判断状态是否合法
def safe(s):# 下面是要排除的条件,并且给出了为什么要排除的理由# s.m > M or s.m < 0 题目要求传教士的数量# s.c < 0 or (s.m != 0 and s.m < s.c) 有教士时,野兽的数量不能大于教士# s.m != M and M - s.m < C - s.c 对岸不全是怪兽时,对岸上的怪兽不能大于对岸上的教士if s.m > M or s.m < 0 or s.c > C or s.c < 0 or (s.m != 0 and s.m < s.c) or (s.m != M and M - s.m < C - s.c):return Falseelse:# 状态合法return True# 启发函数
def h(s):# 传教士数量+野人数量-船的位置与船的最大容量的乘积# 我们希望这个值越越小越好# 他的含义:岸上传教士数量+岸上野人数量之后# 如果这船在对岸(这是我们希望的,说明顺利渡河),于是我们就减上K*s.b# 如果船不在对岸,这不是我们希望的,所以不进行任何减数的操作(K=0)return s.m + s.c - K * s.b# 判断两个状态是否相同
def equal(a, b):if np.array_equal(a.node, b.node):return 1, belse:return 0, b# 判断当前状态是否与父状态一致
# new 是新结点,s是它的父节点
def back(new, s):if s.father is None:return Falsec = b = s.fatherwhile True:# 不断回溯,去找他的父结点是否与new结点相同a, c = equal(new, b)if a:return Trueb = c.fatherif b is None:# 此时找到的b是根结点,停止搜索return False# 根据f值对open_list进行排序
def open_sort(l):l.sort(key=lambda x: x.f)# 在open_list和closed_list中查找具有相同MCB属性的节点
def in_list(new, l):for item in l:if np.array_equal(new.node, item.node):return True, itemreturn False, None# A*算法
def A_star(s):A = []global open_list, closed_listopen_list = [s]closed_list = []while True:  # open_list不为空for i in open_list:if np.array_equal(i.node, goal.node):  # 判断是否为目标节点A.append(i)open_list.remove(i)if not open_list:breakget = open_list[0]open_list.remove(get)  # 从open_list中移除get节点closed_list.append(get)  # 将get节点加入closed_list# 获取get的子节点并考虑是否将其加入open_listfor i in range(M + 1):  # 船上传教士数量for j in range(C + 1):  # 船上野人数量# 船上人数非法: 1:船上无人或者2:船上的人大于规定的载客数或者3:船上有教士并且野怪的数量大于教士if i + j == 0 or i + j > K or (i != 0 and i < j):continue# 找到满足要求的相对于刚遍历完的结点get的下一个状态if get.b == 1:  # 当前船在左岸,下一个状态船在右岸new = State(get.m - i, get.c - j, 0)child.append(new)else:  # 当前船在右岸,下一个状态船在左岸new = State(get.m + i, get.c + j, 1)child.append(new)# safe(new)判断是否非法# back(new, get)这个相对于get结点的孩子回到父状态? TODOif not safe(new) or back(new, get):  # 状态非法或已经回到父状态child.pop()else:# 定义它的上一个状态的结点new.father = get# 孩子结点层级加1new.g = get.g + 1# 父亲的结点层级+父亲的启发性层度new.f = get.g + h(get)open_list.append(new)open_sort(open_list)return A# 递归打印路径
def print_path(f):if f is None:return# 先递归打印父结点的,再打印自己的结点print_path(f.father)print(f.node)# print(f.f)if __name__ == '__main__':print('传教士数量:%d, 野人数量:%d, 船的最大容量:%d' % (M, C, K))final = A_star(init)print("共有%d种方案" % len(final))if final:c = 1for i in final:print('第%d个方案如下' % c)print_path(i)c += 1else:print('没有找到解决方案!')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/234881.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

EasyMicrobiome-易扩增子、易宏基因组等分析流程依赖常用软件、脚本文件和数据库注释文件

啥也不说了&#xff0c;这个好用&#xff0c;给大家推荐&#xff1a;YongxinLiu/EasyMicrobiome (github.com) 大家先看看引用文献吧&#xff0c;很有用&#xff1a;https://doi.org/10.1002/imt2.83 还有这个&#xff0c;后面马上介绍&#xff1a;YongxinLiu/EasyAmplicon: E…

mabatis基于xml方式和注解方式实现多表查询

前面步骤 http://t.csdnimg.cn/IPXMY 1、解释 在数据库中&#xff0c;单表的操作是最简单的&#xff0c;但是在实际业务中最少也有十几张表&#xff0c;并且表与表之间常常相互间联系&#xff1b; 一对一、一对多、多对多是表与表之间的常见的关系。 一对一&#xff1a;一张…

zookeeper 单机伪集群搭建简单记录(实操课程系列)

本系列是zookeeper相关的实操课程&#xff0c;课程测试环环相扣&#xff0c;请按照顺序阅读测试来学习zookeeper 1、官方下载加压后&#xff0c;根目录下新建data和log目录&#xff0c;然后分别拷贝两份&#xff0c;分别放到D盘&#xff0c;E盘&#xff0c;F盘 2、data目录下面…

基于SSM的影视创作论坛设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

docker集群的详解以及超详细搭建

文章目录 一、问题引入1. 多容器位于同一主机2. 多容器位于不同主机 二、介绍三、特性四、概念1. 节点nodes2. 服务(service)和任务(task)3. 负载均衡 五、docker网络1. overlay网络 六、docker集群搭建1. 环境介绍2. 创建集群3. 集群网络4. 加入工作节点 七、部署可视化界面po…

[NOIP2016 普及组] 回文日期

枚举好题&#xff0c;直接枚举答案 看看在不在范围内就行了 注意二月份 92200229是合法的~ 82200228也是合法的&#xff01; #include<bits/stdc.h> using namespace std;map<int,int>mp;int main() {mp[1] mp[3] mp[5] mp[7] mp[8] mp[10] mp[12] 31;mp[…

【MATLAB】异常数据识别

基于分位数的异常点识别 首先&#xff0c;给定了一个原始数据序列x。然后&#xff0c;计算了序列x的上四分位数和下四分位数&#xff0c;并根据这两个值计算了异常点的阈值。上四分位数减去1.5倍的四分位数范围得到异常值下界&#xff0c;下四分位数加上1.5倍的四分位数范围得…

5年经验之谈 —— 接口测试主要测哪些方面?

当今互联网时代&#xff0c;接口测试已经成为软件测试的一个重要组成部分。接口测试是指对系统各个接口进行验证&#xff0c;确保接口的正确性、稳定性和安全性。接口测试是软件开发过程中不可缺少的环节&#xff0c;它旨在确保接口能够正常工作&#xff0c;并且满足所需要的规…

世微AP5125 DC-DC降压恒流 LED车灯电源驱动IC SOT23-6

产品描述 AP5125 是一款外围电路简单的 Buck 型平均电流检测模式的 LED 恒流驱动器&#xff0c;适用于 8-100V 电压范围的非隔离式大功率恒流 LED 驱动领域。芯片采用固定频率 140kHz 的 PWM 工作模式&#xff0c; 利用平均电流检测模式&#xff0c;因此具有优异的负载调整 率…

ELK----日志分析

ELK相关知识 ELK的概念与组件 ELK平台是一套完整的日志集中处理解决方案&#xff0c;将 ElasticSearch、Logstash 和 Kiabana 三个开源工具配合使用&#xff0c; 完成更强大的用户对日志的查询、排序、统计需求。 E&#xff1a;ElasticSearch &#xff08;ES&#xff09; ES是…

免费的电脑AI写作工具-5款好用的智能AI写作软件

随着人工智能&#xff08;AI&#xff09;技术的不断进步&#xff0c;电脑AI写作已经成为现代写作领域的一项不可或缺的工具。通过深度学习和自然语言处理的融合&#xff0c;AI写作软件得以模拟人类的创造性和表达能力&#xff0c;为我们提供了快速、高效地生成优质文字内容的可…

Python使用——发送Get请求,模拟http请求 进行SSH连接服务器

前言 本篇博客是python开发的使用案例博客&#xff0c;结合一些具体的案例进行阐述&#xff0c;本篇博客主要内容是使用Python发送Get请求&#xff0c;模拟http请求&#xff0c;后面可以搞个爬虫出来&#xff0c;另外就是如何使用Python进行SSH连接服务器。 其他相关的博客文…