A*算法解决传教士—野人过河问题

算法原理

1、A算法的基本原理分析;
在或图的一般搜索算法中,如果在搜索过程的步骤⑦利用估价函数f(n)=g(n)+h(n)对open表中的节点进行排序,则该搜索算法为A算法。
g(n):从初始节点到n的实际代价
因为n为当前节点,搜索已达到n点,所以g(n)可计算出。
h(n):启发函数,从n到目标节点的最佳路径的估计代价。
因为尚未找到解路径,所以h(n)仅仅是估计值。
对A算法中的g(n)和h(n)做出限制:
g(n) >= g
(n)(g*(n)为S0到n的最小费用)
-h(n) <= h*(n)(h*(n)为n到Sg的实际最小费用)
则算法被称为A*算法。

2、传教士—野人过河问题的知识表示方法分析;
在这个问题中,需要考虑:
1、两岸的传教士人数和野人人数 2、船在左岸还是在右岸
已知:传教士和野人数:N(两者默认相同),船的最大容量:K
定义:M:左岸传教士人数 C:左岸野人人数 B:左岸船个数
可用一个三元组来表示左岸状态,即S=(M, C, B)。
约束条件:M>=0,C>=0,B=1或0
已知左岸状态,右岸的状态为:
右岸传教士人数:M’=N-M
右岸野人人数:C’=N-C
右岸船数:B’=1-B
满足同样的约束条件

3、针对传教士—野人过河问题的A算法详细分析
(1)A
算法求解传教士和野人过河问题,主要实现过程:
①使用状态空间法将问题的求解抽象为状态空间的搜索。
②根据A算法的思想、A算法的具体步骤、设计估价函数的方法,针对传教士–野人过河问题设计出估价函数f(n),给出条件约束函数。
(2)估价函数设计:f(n)=g(n)+M+C-K*B

  • h(n)=M+C-K*B把状态转换后左岸剩余人数作为启发性信息

合理性分析:
本问题中,在满足条件约束的前提下,总是希望能使左岸的人数最少。当左岸有船时,应当使船每次都满负荷运载,即运KB人过河。
然而,在最大运载量为K的情况下,状态转换后左岸的剩余人数不可能小于M+C-K
B,即从节点n到目标节点的最小代价h*(n)不可能小于h(n) ,因此,满足A算法的条件限制h(n)<=h(n)。
(3)本问题中操作是指用船把传教士或野人从河的左岸运到右岸,或者从河的右岸运到左岸,并且每个操作都应该满足以下3个条件:
①船至少有一个人(M或C)操作,离开岸边的M和C的减少数目等于到达岸边的M和C的增加数目。
②每次操作,船上的人数不得超过K个。
③操作应保证不产生非法状态。

设计思路

1、设计状态空间表示方式
可用一个三元组来表示左岸状态,即S=(M, C, B),将所有扩展的节点和原始节点存放在同一列表中。初始状态为(N,N,1),目标状态为(0,0,0),问题的求解转换为在状态空间中,找到一条从状态(N, N, 1)到状态(0, 0, 0)的最优路径。
例:在3传教士3野人问题中,初始状态为(3,3,1),目标状态为(0,0,0)。
当1野人离开左岸到达右岸后,原状态变为p = [(3,2,0),(3,3,1)],p[0]为当前状态,而列表最后一个为初始状态,只要当p[0] = (0,0,0)则完成搜索。
2、节点拓展方法与合法状态判断
(1)节点拓展:通过减少和增加传教士或野人的数量来拓展节点。
当船在左岸(B=1):①减少野人 ②减少传教士 ③减少野人和传教士
当船在右岸(B=0):①增加野人 ②增加传教士 ③增加野人和传教士
(2)合法状态判断
①左岸传教士数量等于总数或左岸传教士为0:C>=0,C<=N
②左岸传教士数量基于0到N之间时: C >=0 , M >= C , M <= N , C <= N , N-M >= N-C
③其他状态为不合法

3、搜索过程
①建立只含有初始节点S的搜索图G,把S放到OPEN表中;
②建立CLOSED表,其初始值为空表;
③若OPEN表是空表,则失败退出;
④选择OPEN表中第一个节点,把它从OPEN表移出并放进CLOSED表中,称此节点为节点n;
⑤若n为目标节点,则有解并成功退出。
⑥沿指针追踪图G中从n到S这条路径得到解(指针在步骤⑦中设置);
⑦扩展n,生成不是n的祖先的那些后继节点的集合M,把M的这些成员作为n的后继节点添入图G中;
对M中子节点进行如下处理:
-对没在G中出现过的(即没在OPEN或CLOSED表中出现过的)M成员设置一个指向n的指针,把M的这些成员加进OPEN表;
-已在OPEN或CLOSED表中的每个M成员,确定是否需要更改指向n的指针方向;
-已在CLOSED表中的每个M成员,确定是否需要更改图G中它的每个后裔节点指向父节点的指针。
⑧按某种方式或按某个试探值,重排OPEN表;
⑨转步骤③。

完整代码

def GJ(this,k):#估价函数计算 h(n) = M + C - K * Breturn this[0] + this[1] - k * this[2]def creat(array,M,C,B,N):#判断生成节点是否符合规则、判断是否重复P = array[:]if M == N :#左岸传教士数量等于总数if  C >=0  and  C <= N :P.insert(0,[M,C,1-B])for i in open:if P[0] == i[0]:return Falsefor i in closed:if P[0] == i[0]:return Falseopen.append(P)return Trueelse:return Falseelif M > 0 :#左岸传教士数量基于0到N之间时if  C >=0 and M >= C and M <= N and C <= N and N-M >= N-C:P.insert(0,[M,C,1-B])for i in open:if P[0] == i[0]:return Falsefor i in closed:if P[0] == i[0]:return Falseopen.append(P)return Trueelse:return Falseelif M == 0:#左岸传教士为0if  C >= 0 and C <= N:P.insert(0, [M, C, 1 - B])for i in open:if P[0] == i[0]:return Falsefor i in closed:if P[0] == i[0]:return Falseopen.append(P)return Trueelse:return Falseelse:return Falseif  __name__ == '__main__':N = int(input("传教士和野人的人数(默认相同):"))K =int(input("船的最大容量:"))open = []  #创建open表closed = [] #创建closed表sample = [N,N,1] #初始状态goal = [0,0,0]#目标状态open.append([sample])creatpoint = searchpoint = 0while(1):if sample == goal:print("初始状态为目标状态!")breakif len(open) == 0:print("未搜索到解!")breakelse:this = open.pop(0)closed.append(this)if this[0] == goal:print("搜索成功!")print('共生成节点数:{},共搜索节点数:{}'.format(creatpoint,searchpoint + 1))print('过河方案如下:')print('      [M, C, B]')for i in this[::-1]:print('---->',i)exit()#扩展节点searchpoint += 1if this[0][2] == 1 :#船在左岸时for i in range(1,K+1):#只if creat(this,this[0][0]-i,this[0][1],this[0][2],N):creatpoint += 1for i in range(1,K+1):if creat(this,this[0][0],this[0][1]-i,this[0][2],N):creatpoint += 1for i in range(1,K):for r in range(1,K-i+1):if creat(this,this[0][0] - i,this[0][1] - r, this[0][2],N):creatpoint += 1else:#船在右岸时for i in range(1,K+1):if creat(this,this[0][0]+i,this[0][1],this[0][2],N):creatpoint += 1for i in range(1,K+1):if creat(this,this[0][0],this[0][1]+ i,this[0][2],N):creatpoint += 1for i in range(1,K):for r in range(1,K-i+1):if creat(this,this[0][0] + i,this[0][1] + r, this[0][2],N):creatpoint += 1#计算估计函数h(n) = M + C - K * B 重排open表for x in range(0,len(open)-1):m = xfor y in range(x+1,len(open)):if  GJ(open[x][0],K) >  GJ(open[y][0],K):m = yif m != x:open[x],open[m] = open[m],open[x]

运行结果

参数设置1:N = 3,K =2
初始状态:(3,3,1),目标状态:(0,0,0)
实验结果:

参数设置2:N = 5,K =3
初始状态:(5,5,1),目标状态:(0,0,0)
实验结果:

参数设置3:N = 10,K =4
初始状态:(10,10,1),目标状态:(0,0,0)
实验结果:

A*算法解决传教士—野人过河问题相关推荐

  1. 过河问题(牛虎过河、商人仆人过河、农夫妖怪过河、传教士野人过河)(第2届第2题)

    ▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ 最新链接 题目要求 问题描述:三只牛三只虎过河,船最多只能容纳两只动物,且船在往返途中不能为空. ...

  2. 传教士与野人过河问题 人工智能实验算法

    问题描述 有 N 个传教士和 N 个野人来到河边渡河,河岸有一条船,每次至多可供 k 人乘渡.问:传教士为了安全起见,应如何规划摆渡方案,使得任何时刻, 河两岸以及船上的野人数目总是不超过传教士的数目 ...

  3. python深度优先搜索传教士和野人_ai1 带回溯的深度优先策略:解决经典野人传教士过河问题的求解:三个修道士和三个野人过河 - 下载 - 搜珍网...

    带回溯的深度优先策略:解决经典野人传教士过河问题的求解:三个修道士和三个野人过河,船一次最多只能载两个人,在任何时候修道士的人数不能少于野人人数,否则野人会吃掉修道士.找出六个人顺利过河的所有方案. ...

  4. 1. A星算法解决修道士与野人问题

    A星算法解决修道士与野人问题 1. 运行环境 CPU:I5-10400 内存:16GB 系统:Win10 64位专业版,20H2 IDE:Vistual Studio 2019专业版 2. 问题描述 ...

  5. 用BFS(广度优先搜索queuelist)算法解决农夫过河问题

    用BFS(广度优先搜索queue&&list)算法解决农夫过河问题 一.问题需求分析 一个农夫带着一只狼.一只羊和一棵白菜,身处河的南岸.他要把这些东西全部运到北岸.问题是他面前只有一 ...

  6. 修道士和野人过河问题 A*算法 人工智能

    /** * 2014-08-25 by Liy * 修道士和野人过河问题,一共有3个修道士和3个野人,1条船 * 1.船最多可乘坐2人 * 2.两岸边 野人的数量不能多于修道士的数量,否则修道士会被吃 ...

  7. 传教士与野人过河问题(A*搜索 C++)

    传教士与野人过河问题: 任意时刻,左岸.右岸.船上如果传教士人数少于野人人数,传教士就会被野人吃掉.当然野人会划船.传教士人数为0也是可以的. 启发函数 f=g+h.  g当前结点所在解空间树的深度. ...

  8. JAVA野人_Java实现传教士与野人过河问题

    1  问题定义 河的两岸有三个传教士和三个野人需要过河,目前只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于传教士的人数,那么传教士就会被野人攻击,怎么找出一种安全的渡河方案呢? ...

  9. 人工智能--野人过河

    课程简介 人工智能(Artificial Intelligence),英文缩写为AI.它是研究.开发用于模拟.延伸和扩展人的智能的理论.方法.技术及应用系统的一门新的技术科学.人工智能的定义可以分为两 ...

  10. 人工智能实践作业-修道士和野人过河问题

    人工智能实践作业-修道士和野人过河问题: 用编程语言编写和调试一个基于深度优先搜索法的解决"野人与传教士过河"问题的程序.目的是学会运用知识表示方法和搜索策略求解一些考验智力的简单 ...

最新文章

  1. Python使用matplotlib函数subplot可视化多个不同颜色的折线图、自定义数据点的形状、自定义折线图的颜色
  2. 兼容多种屏幕分辨率的通栏大图实现方法
  3. MyBatis Plus——分页插件【PaginationInnerInterceptor】
  4. engagement center tile的配置
  5. ISO语言代码和国家代码+Locale常量+ISO货币符号
  6. mysql 查出相差年数_MySQL计算两个日期相差的天数、月数、年数
  7. python安装函数库pip网址_批量安装python库函数---pip
  8. [Redux/Mobx] Mobx和Redux有什么区别?
  9. 波形分析--SPI数据
  10. office 公式编辑器 插入花体格式字母
  11. HTML5+CSS大作业——宝马轿车网页设计(6页) web前端设计与开发期末作品/期末大作业
  12. 支付宝授权登陆php,支付宝app登录授权的infoStr授权登录流程
  13. 基于springboot的医院体检预约管理系统
  14. 微店获得微店商品详情API,使用和获取说明
  15. 小程序视频不显示进度条,且不能滑屏快进
  16. 一个女测试工程师的成长之路
  17. Linux下多个进程可以同时打开同一个文件吗?文件描述符与打开文件的关系?
  18. java 栈 先进先出_堆是先进先出,栈是先进后出
  19. vue-element-admin改造顶部一级导航,侧边二级导航+权限路由
  20. 员工如何应对工作中的挫败感

热门文章

  1. CSPS Oct目标
  2. “衣带渐宽终不悔,为伊消得人憔悴”的赏析
  3. 学习笔记(二十一)—— 使用SMTP发送电子邮件
  4. 编写程序,从键盘输入一个三位整数,将它们逆序输出。例如:输入456 ,输出654。
  5. 电子计算机的发展和应用教案,第1课 追寻发展的足迹——计算机的发展与应用...
  6. trackmaker翻译_体育翻译滑雪中英对照翻译
  7. 吉林市一日游规格说明书
  8. grunt源码解析1——如何安装grunt:grunt命令是怎样运行起来的
  9. 怎么解决电脑任务管理器被系统管理员停用?
  10. CS294(285)策略梯度学习笔记