修道士与野人问题教学文案
- 格式:doc
- 大小:274.00 KB
- 文档页数:20
人工智能试题及答案【篇一:人工智能经典试题及答案】ass=txt>2.8 设有如下语句,请用相应的谓词公式分别把他们表示出来:s(1) 有的人喜欢梅花,有的人喜欢菊花,有的人既喜欢梅花又喜欢菊花。
解:定义谓词dp(x):x是人l(x,y):x喜欢y其中,y的个体域是{梅花,菊花}。
将知识用谓词表示为:(?x )(p(x)→l(x, 梅花)∨l(x, 菊花)∨l(x, 梅花)∧l(x, 菊花))(2) 有人每天下午都去打篮球。
解:定义谓词p(x):x是人b(x):x打篮球a(y):y是下午将知识用谓词表示为:a(?x )(?y) (a(y)→b(x)∧p(x))(3) 新型计算机速度又快,存储容量又大。
解:定义谓词nc(x):x是新型计算机f(x):x速度快b(x):x容量大将知识用谓词表示为:(?x) (nc(x)→f(x)∧b(x))(4) 不是每个计算机系的学生都喜欢在计算机上编程序。
解:定义谓词s(x):x是计算机系学生l(x, pragramming):x喜欢编程序u(x,computer):x使用计算机将知识用谓词表示为:? (?x) (s(x)→l(x, pragramming)∧u(x,computer))(5) 凡是喜欢编程序的人都喜欢计算机。
解:定义谓词p(x):x是人l(x, y):x喜欢y将知识用谓词表示为:(?x) (p(x)∧l(x,pragramming)→l(x, computer))2.9 用谓词表示法求解机器人摞积木问题。
设机器人有一只机械手,要处理的世界有一张桌子,桌上可堆放若干相同的方积木块。
机械手有4个操作积木的典型动作:从桌上拣起一块积木;将手中的积木放到桌之上;在积木上再摞上一块积木;从积木上面拣起一块积木。
积木世界的布局如下图所示。
图机器人摞积木问题解:(1) 先定义描述状态的谓词clear(x):积木x上面是空的。
(x, y):积木x在积木y的上面。
野人与修道士问题(Missionaries-and-Cannibals Problem )[修道士与野人问题]:三个野人与三个传教士来到河边,打算乘一只船从右岸渡到左岸去,该船的最大负载能力为两个人。
在任何时候,如果野人人数超过传教士人数,那么野人就会把传教士吃掉。
用状态空间法表示修道士与野人问题并设计编写计算机程序求问题的解。
问题分析:从上图可知,修道士、野人和船一共有六种可能,M L 、C L 、B L 、M R 、C R 、B R 。
可以表示为q =(M ,C ,B ),其中m 表示修道士的数目(0、1、2、3)、c 表示野人的数目(0、1、2、3)、b 表示船在左岸(1)或右岸(0)。
1、定义状态的描述形式:(m ,c ,b )2、表示所有可能的状态,并确定初始状态集和目标状态集:s0(3,3,1) s8(1,3,1) s16(3,3,0) s24(1,3,0)s1(3,2,1) s9(1,2,1) s17(3,2,0) s25(1,2,0)s2(3,1,1) s10(1,1,1) s18(3,1,0) s26(1,1,0)s3(3,0,1) s11(1,0,1) s19(3,0,0) s27(1,0,0)s4(2,3,1) s12(0,3,1) s20(2,3,0) s28(0,3,0)s5(2,2,1) s13(0,2,1) s21(2,2,0) s29(0,2,0)s6(2,1,1) s14(0,1,1) s22(2,1,0) s30(0,1,0)s7(2,0,1) s15(0,0,1) s23(2,0,0) s31(0,0,0)初始状态:(3,3,1)目标状态:(0,0,0)3、定义算符:L ij :把i 个修道士,j 个野人从河的左岸送到右岸R ij :把i 个修道士,j 个野人从河的右岸送到左岸整个问题就抽象成了怎样从初始状态经中间的一系列状态达到目标状态。
问修道士M野 人C 左L 右R题状态的改变是通过划船渡河来引发的,所以合理的渡河操作就成了通常所说的算符,根据题目要求,可以得出以下5个算符(按照渡船方向的不同,也可以理解为10个算符):渡1野人、渡1牧师、渡1野人1牧师、渡2野人、渡2牧师即:L01或R01,L10或R10,L11或R11,L02或R02,L20或R204、状态空间图:5、设计编写计算机程序求问题的解:算法:在应用状态空间表示和搜索方法时,用(M,C,B)来表示状态描述,其中M和C分别表示在左岸的传教士与野人数。
修道⼠和野⼈问题 休闲时刻看看神经⽹络⽅⾯的书,发现了修道⼠和野⼈的问题,不禁勾引起我写算法的欲望,曾经的三只⼤⽼虎三只⼩⽼虎过河问题、⼈狼⽺⽩菜过河问题、汉诺塔、哈夫曼等等各种算法瞬间在脑海中约隐约现,修道⼠和野⼈问题我以前好像没有解开,中午吃饭的时候在脑海中重新构造思路,下午耗了点时间把它⼲掉。
(算法不在代码⾥,⽽在思想中;所以尽量不要看我的代码,⽽要仔细分析我写的思路) 题⽬: 设有3个修道⼠和3个野⼈来到河边,打算⽤⼀条船从河的左岸渡到河的右岸。
但该船每次只能装载两个⼈,在任何岸边野⼈的数⽬都不得超过修道⼠的⼈数,否则修道⼠就会被野⼈吃掉。
假设野⼈服从任何⼀种过河安排,请问如何规划过河计划才能把所有⼈都安全地渡过河去。
⾸先考虑总共有(3+1)*(3+1)= 16 种不同的状态(因为左岸可以有0,1,2,3个传教⼠,左岸可以有0,1,2,3个野⼈),所以可以考虑使⽤穷举法。
使⽤如下C#程序语⾔:int MaxNum = 3;for (int monk = MaxNum; monk >= 0; monk--){for (int savage = MaxNum; savage >= 0; savage--){Console.Write("{{" + monk + "," + savage + "},{" + (MaxNum - monk) + "," + (MaxNum - savage) + "}} ");}Console.Write("\n");}⽣成16种状态图↓↓↓↓↓↓↓↓↓↓↓状态图含义:{a,b}:a,左岸修道⼠数量;b,左岸野⼈数量。
--------仅考虑左岸传教⼠和野蛮⼈数量(所有状态图)------------------------{3,3} {3,2} {3,1} {3,0}{2,3} {2,2} {2,1} {2,0}{1,3} {1,2} {1,1} {1,0}{0,3} {0,2} {0,1} {0,0}其中{3,3}是起始状态图;{0,0}是终⽌状态图。
第二章知识表示习题参考解答2.3 练习题2.1 什么是知识?它有哪些特性?有哪几种分类方法?2.2 何谓知识表示? 陈述性知识表示法与过程性知识表示法的区别是什么?2.3 在选择知识的表示方法时,应该考虑哪些主要因素?2.4 一阶谓词逻辑表示法适合于表示哪种类型的知识?它有哪些特点?2.5 请写出用一阶谓词逻辑表示法表示知识的步骤。
2.6 设有下列语句,请用相应的谓词公式把它们表示出来:(1)有的人喜欢梅花,有的人喜欢菊花,有的人既喜欢梅花又喜欢菊花。
(2)他每天下午都去玩足球。
(3)太原市的夏天既干燥又炎热。
(4)所有人都有饭吃。
(5)喜欢玩篮球的人必喜欢玩排球。
(6)要想出国留学,必须通过外语考试。
2.7 房内有一只猴子、一个箱子,天花板上挂了一串香蕉,其位置关系如图2. 11所示,猴子为了拿到香蕉,它必须把箱子推到香蕉下面,然后再爬到箱子上。
请定义必要的谓词,写出问题的初始状态(即图2.16所示的状态)、目标状态(猴子拿到了香蕉,站在箱子上,箱子位于位置b)。
图2.11 猴子摘香蕉问题2.8 对习题2.7中的猴子摘香蕉问题,利用一阶谓词逻辑表述一个行动规划,使问题从初始状态变化到目标状态。
2.9 产生式的基本形式是什么?它与谓词逻辑中的蕴含式有什么共同处及不同处?2.10 何谓产生式系统?它由哪几部分组成?2.11 产生式系统中,推理机的推理方式有哪几种?在产生式推理过程中,如果发生策略冲突,如何解决?2.12 设有下列八数码难题:在一个3×3的方框内放有8个编号的小方块,紧邻空位的小方块可以移入到空位上,通过平移小方块可将某一布局变换为另一布局(如图2.12所示)。
请用产生式规则表示移动小方块的操作。
2831231684754765S0S g图2.12 习题2.12的图图2.13 习题2.13的图2.13 推销员旅行问题:设有五个相互可直达且距离已知的城市A、B、C、D、E,如图2.13所示,推销员从城市A出发,去其它四城市各旅行一次,最后再回到城市A,请找出一条最短的旅行路线。
第二章知识表示习题参考解答2.3 练习题2.1 什么是知识?它有哪些特性?有哪几种分类方法?2.2 何谓知识表示? 陈述性知识表示法与过程性知识表示法的区别是什么?2.3 在选择知识的表示方法时,应该考虑哪些主要因素?2.4 一阶谓词逻辑表示法适合于表示哪种类型的知识?它有哪些特点?2.5 请写出用一阶谓词逻辑表示法表示知识的步骤。
2.6 设有下列语句,请用相应的谓词公式把它们表示出来:(1)有的人喜欢梅花,有的人喜欢菊花,有的人既喜欢梅花又喜欢菊花。
(2)他每天下午都去玩足球。
(3)太原市的夏天既干燥又炎热。
(4)所有人都有饭吃。
(5)喜欢玩篮球的人必喜欢玩排球。
(6)要想出国留学,必须通过外语考试。
2.7 房内有一只猴子、一个箱子,天花板上挂了一串香蕉,其位置关系如图2. 11所示,猴子为了拿到香蕉,它必须把箱子推到香蕉下面,然后再爬到箱子上。
请定义必要的谓词,写出问题的初始状态(即图2.16所示的状态)、目标状态(猴子拿到了香蕉,站在箱子上,箱子位于位置b)。
图2.11 猴子摘香蕉问题2.8 对习题2.7中的猴子摘香蕉问题,利用一阶谓词逻辑表述一个行动规划,使问题从初始状态变化到目标状态。
2.9 产生式的基本形式是什么?它与谓词逻辑中的蕴含式有什么共同处及不同处?2.10 何谓产生式系统?它由哪几部分组成?2.11 产生式系统中,推理机的推理方式有哪几种?在产生式推理过程中,如果发生策略冲突,如何解决?2.12 设有下列八数码难题:在一个3×3的方框内放有8个编号的小方块,紧邻空位的小方块可以移入到空位上,通过平移小方块可将某一布局变换为另一布局(如图2.12所示)。
请用产生式规则表示移动小方块的操作。
2831231684754765S0S g图2.12 习题2.12的图图2.13 习题2.13的图2.13 推销员旅行问题:设有五个相互可直达且距离已知的城市A、B、C、D、E,如图2.13所示,推销员从城市A出发,去其它四城市各旅行一次,最后再回到城市A,请找出一条最短的旅行路线。
1、数据、信息和知识(1)数据是信息的载体; (2)信息是数据的解释 (3)知识是关联的信息;(4)元知识是使用知识的知识。
图1-1 知识的金字塔结构2.知识的特点:相对正确性,不确定性(获得的信息不完全),知识是可表达的(数据、文字、图形、公式等),可利用性(用来改造世界)。
3.知识的分类按知识的获得是否依赖于感觉器官来划分,知识可分为先验知识和后验知识。
先验知识不依赖于感觉器官,一般是正确的; 后验知识依赖于感觉器官,是相对正确的。
按知识的作用分为说明性知识、过程性知识、控制性知识。
说明性知识:一般陈述句, “是什么”; 过程性知识:如何去做某事;控制性知识:相当于元知识,如何决定去做某事。
按知识的作用范围可分为常识性知识和领域性知识。
按确定性可分为确定性知识和不确定性知识。
按人类思维方式和知识的结构及表现形式分为逻辑性知识和形象性知识。
4、知识表示知识表示技术研究知识以什么样的形式表示才能便于在计算机中存储和处理。
知识表示是对人类知识的一种形式化描述;知识表示的过程就是把知识编码成计算机能处理的数据结构的过程; 知识表示是数据结构与控制结构的统一。
3、知识表示:知识表示是指知识在计算机中的表示方法和表示形式,它涉及到知识的逻辑结构和物理结构。
主要表示方法有:状态空间、语义网络、谓词逻辑、框架知识表示技术研究的要求:能否充分表示相关领域的知识; 是否是有利于对知识的利用;是否便于在计算机中的组织和管理; 是否便于理解和实现。
4、几种知识表示方法 1、状态空间法 2、产生式表示法 3、谓词逻辑表示法 4、语义网络表示法 5、框架表示法其它:面向对象表示、剧本表示、过程表示等。
元知识 知识 信息 数据 噪声1.2 状态空间表示法图1-2 水的状态转换图图1-3 气球的状态转换图 怎样描述状态及状态的改变 (1)状态状态是描述某一类事物中各事物之间的差异而引入的最少的一组变量。
的有序集合。
人工智能试题及答案【篇一:人工智能经典试题及答案】ass=txt>2.8 设有如下语句,请用相应的谓词公式分别把他们表示出来:s(1) 有的人喜欢梅花,有的人喜欢菊花,有的人既喜欢梅花又喜欢菊花。
解:定义谓词dp(x):x是人l(x,y):x喜欢y其中,y的个体域是{梅花,菊花}。
将知识用谓词表示为:(?x )(p(x)→l(x, 梅花)∨l(x, 菊花)∨l(x, 梅花)∧l(x, 菊花))(2) 有人每天下午都去打篮球。
解:定义谓词p(x):x是人b(x):x打篮球a(y):y是下午将知识用谓词表示为:a(?x )(?y) (a(y)→b(x)∧p(x))(3) 新型计算机速度又快,存储容量又大。
解:定义谓词nc(x):x是新型计算机f(x):x速度快b(x):x容量大将知识用谓词表示为:(?x) (nc(x)→f(x)∧b(x))(4) 不是每个计算机系的学生都喜欢在计算机上编程序。
解:定义谓词s(x):x是计算机系学生l(x, pragramming):x喜欢编程序u(x,computer):x使用计算机将知识用谓词表示为:? (?x) (s(x)→l(x, pragramming)∧u(x,computer))(5) 凡是喜欢编程序的人都喜欢计算机。
解:定义谓词p(x):x是人l(x, y):x喜欢y将知识用谓词表示为:(?x) (p(x)∧l(x,pragramming)→l(x, computer))2.9 用谓词表示法求解机器人摞积木问题。
设机器人有一只机械手,要处理的世界有一张桌子,桌上可堆放若干相同的方积木块。
机械手有4个操作积木的典型动作:从桌上拣起一块积木;将手中的积木放到桌之上;在积木上再摞上一块积木;从积木上面拣起一块积木。
积木世界的布局如下图所示。
图机器人摞积木问题解:(1) 先定义描述状态的谓词clear(x):积木x上面是空的。
(x, y):积木x在积木y的上面。
第2章知识表示方法部分参考答案2.8设有如下语句,请用相应的谓词公式分别把他们表示出来:(1)有的人喜欢梅花,有的人喜欢菊花,有的人既喜欢梅花又喜欢菊花。
解:定义谓词P(x):x是人L(x,y):x喜欢y其中,y的个体域是{梅花,菊花}。
将知识用谓词表示为:(∃x )(P(x)→L(x, 梅花)∨L(x, 菊花)∨L(x, 梅花)∧L(x, 菊花))(2) 有人每天下午都去打篮球。
解:定义谓词P(x):x是人B(x):x打篮球A(y):y是下午将知识用谓词表示为:(∃x )(∀y) (A(y)→B(x)∧P(x))(3)新型计算机速度又快,存储容量又大。
解:定义谓词NC(x):x是新型计算机F(x):x速度快B(x):x容量大将知识用谓词表示为:(∀x) (NC(x)→F(x)∧B(x))(4) 不是每个计算机系的学生都喜欢在计算机上编程序。
解:定义谓词S(x):x是计算机系学生L(x, pragramming):x喜欢编程序U(x,computer):x使用计算机将知识用谓词表示为:¬(∀x) (S(x)→L(x, pragramming)∧U(x,computer))(5)凡是喜欢编程序的人都喜欢计算机。
解:定义谓词P(x):x是人L(x, y):x喜欢y将知识用谓词表示为:(∀x) (P(x)∧L(x,pragramming)→L(x, computer))2.9 用谓词表示法求解机器人摞积木问题。
设机器人有一只机械手,要处理的世界有一张桌子,桌上可堆放若干相同的方积木块。
机械手有4个操作积木的典型动作:从桌上拣起一块积木;将手中的积木放到桌之上;在积木上再摞上一块积木;从积木上面拣起一块积木。
积木世界的布局如下图所示。
解:(1) 先定义描述状态的谓词CLEAR(x):积木x 上面是空的。
ON(x, y):积木x 在积木y 的上面。
ONTABLE(x):积木x 在桌子上。
HOLDING(x):机械手抓住x 。
第2章知识表示方法参考答案2.8设有如下语句,请用相应的谓词公式分别把他们表示出来:(1)有的人喜欢梅花,有的人喜欢菊花,有的人既喜欢梅花又喜欢菊花。
解:定义谓词P(x):x是人L(x,y):x喜欢y其中,y的个体域是{梅花,菊花}。
将知识用谓词表示为:(∃x )(P(x)→L(x, 梅花)∨L(x, 菊花)∨L(x, 梅花)∧L(x, 菊花))(2) 有人每天下午都去打篮球。
解:定义谓词P(x):x是人B(x):x打篮球A(y):y是下午将知识用谓词表示为:(∃x )(∀y) (A(y)→B(x)∧P(x))(3)新型计算机速度又快,存储容量又大。
解:定义谓词NC(x):x是新型计算机F(x):x速度快B(x):x容量大将知识用谓词表示为:(∀x) (NC(x)→F(x)∧B(x))(4) 不是每个计算机系的学生都喜欢在计算机上编程序。
解:定义谓词S(x):x是计算机系学生L(x, pragramming):x喜欢编程序U(x,computer):x使用计算机将知识用谓词表示为:¬(∀x) (S(x)→L(x, pragramming)∧U(x,computer))(5)凡是喜欢编程序的人都喜欢计算机。
解:定义谓词P(x):x是人L(x, y):x喜欢y将知识用谓词表示为:(∀x) (P(x)∧L(x,pragramming)→L(x, computer))2.9用谓词表示法求解机器人摞积木问题。
设机器人有一只机械手,要处理的世界有一张桌子,桌上可堆放若干相同的方积木块。
机械手有4个操作积木的典型动作:从桌上拣起一块积木;将手中的积木放到桌之上;在积木上再摞上一块积木;从积木上面拣起一块积木。
积木世界的布局如下图所示。
图机器人摞积木问题解:(1) 先定义描述状态的谓词CLEAR(x):积木x上面是空的。
ON(x, y):积木x在积木y的上面。
ONTABLE(x):积木x在桌子上。
HOLDING(x):机械手抓住x。
第五章搜索策略习题参考解答5.1 练习题5.1 什么是搜索?有哪两大类不同的搜索方法?两者的区别是什么?5.2 用状态空间法表示问题时,什么是问题的解?求解过程的本质是什么?什么是最优解?最优解唯一吗?5.3 请写出状态空间图的一般搜索过程。
在搜索过程中OPEN表和CLOSE表的作用分别是什么?有何区别?5.4 什么是盲目搜索?主要有几种盲目搜索策略?5.5 宽度优先搜索与深度优先搜索有何不同?在何种情况下,宽度优先搜索优于深度优先搜索?在何种情况下,深度优先搜索优于宽度优先搜索?5.6 用深度优先搜索和宽度优先搜索分别求图5.10所示的迷宫出路。
图5.10 习题5.6的图5.7 修道士和野人问题。
设有3个修道士和3个野人来到河边,打算用一条船从河的左岸渡到河的右岸去。
但该船每次只能装载两个人,在任何岸边野人的数目都不得超过修道士的人数,否则修道士就会被野人吃掉。
假设野人服从任何一种过河安排,请使用状态空间搜索法,规划一使全部6人安全过河的方案。
(提示:应用状态空间表示和搜索方法时,可用(N m,N c)来表示状态描述,其中N m和N c分别为传教士和野人的人数。
初始状态为(3,3),而可能的中间状态为(0,1),(0,2),(0,3), (1,1),(2,1),(2,2),(3,0),(3,1),(3,2)等。
)5.8 用状态空间搜索法求解农夫、狐狸、鸡、小米问题。
农夫、狐狸、鸡、小米都在一条河的左岸,现在要把它们全部送到右岸去。
农夫有一条船,过河时,除农夫外,船上至多能载狐狸、鸡和小米中的一样。
狐狸要吃鸡,鸡要吃小米,除非农夫在那里。
试规划出一个确保全部安全的过河计划。
(提示:a.用四元组(农夫,狐狸,鸡,米)表示状态,其中每个元素都可为0或1,0表示在左岸,1表示在右岸;b.把每次过河的一种安排作为一个算符,每次过河都必须有农夫,因为只有他可以划船。
)5.9 设有三个大小不等的圆盘A 、B 、C 套在一根轴上,每个圆盘上都标有数字1、2、3、4,并且每个圆盘都可以独立地绕轴做逆时针转动,每次转动90°,初始状态S 0和目标状态S g 如图5.11所示,用宽度优先搜索法和深度优先搜索法求从S 0到S g 的路径。
一、实验目的理解并熟悉掌握使用状态空间搜索法。
二、实验内容设有3个修道士和3个野人来到河边,打算从河的左岸渡到河的右岸去。
但该船每次只能装载两个人,在任何岸边的野人的数目都不得超过修道士的人数,否则修道士就会被野人吃掉。
假设野人服从任何一种过河安排,请使用状态空间搜索法,规划一使全部6人安全过河的方案。
提示:使用状态空间表示和搜索方法时,可用(Nm,Nc)来表示状态描述,其中Nm,Nc分别是传教士和野人的人数。
初始状态为(3,3),而可能的中间状态为(0,1),(0,2),(0,3),(1,1),(2,1),(2,2),(3,0),(3,1),(3,2)等。
三、源代码#include <iostream>using namespace std;#define Max 100struct step{int wild; //每次运送的野人数int monk; //每次运送的传道士数};//共十中运送的方法step AllSteps[] = {{2,0},{1,0},{1,1},{0,1},{0,2}};struct node{int wildLeft; //某一时刻左岸的野人数int monkLeft; //某一时刻左岸的传道士人数bool boat; //某一时刻船是否在左岸true:船在左岸;false:船在右岸int parent; //某一节点的父节点};node Count[Max];//判断是否运送完成bool IsFinish(node a){if(a.wildLeft == 0 && a.monkLeft == 0 && a.boat == false)return true;elsereturn false;}//判断是否为正常状态bool IsValid(node a){if(a.monkLeft < 0 || a.wildLeft < 0 || a.monkLeft > 3 || a.wildLeft > 3)return false;else{if(a.monkLeft == 0 || a.monkLeft == 3)return true;else{if(a.monkLeft >= a.wildLeft && (3 - a.monkLeft) >= (3 - a.wildLeft))return true;}return false;}}//当前结点的状态,parent为结点a在数组中的位置,tag为当前数组的头元素int move(node a, int p, int tag){int i;node temp;//如果船在左岸,则可以选择送至右岸的五种方法if(a.boat){for(i = 0; i < 5; i++){temp.monkLeft = a.monkLeft - AllSteps[i].monk;temp.wildLeft = a.wildLeft - AllSteps[i].wild;temp.boat = !a.boat;temp.parent = p;//如果可以满足此条件:两岸传道士人数必须大于等于也人数,则入队列if(IsValid(temp)){if(a.parent == -1 ||(temp.boat != Count[a.parent].boat || temp.monkLeft != Count[a.parent].monkLeft || temp.wildLeft != Count[a.parent].wildLeft)){Count[tag] = temp;tag++;}}if(IsFinish(temp) || tag >= Max)return tag;}}else{for(i = 5; i < 10; i++){temp.monkLeft = a.monkLeft + AllSteps[i-5].monk;temp.wildLeft = a.wildLeft + AllSteps[i-5].wild;temp.boat = !a.boat;temp.parent = p;//如果可以满足此条件:两岸传道士人数必须大于等于也人数,则入队列if(IsValid(temp)){if(a.parent == -1 ||(temp.boat != Count[a.parent].boat || temp.monkLeft != Count[a.parent].monkLeft || temp.wildLeft != Count[a.parent].wildLeft)){Count[tag] = temp;tag++;}}if(IsFinish(temp) || tag >= Max)return tag;}}return tag;}void main(){int i = 0, tag = 1;int j = 0;//初始状态左岸有三个野人,三个传道士,并且船在左岸Count[i].monkLeft = 3;Count[i].wildLeft = 3;Count[i].boat = true;Count[i].parent = -1;while(!IsFinish(Count[tag - 1]) && tag < Max){tag = move(Count[i], i, tag);i++;cout<< i<<endl;cout << "-------------------------" << endl;}if(tag < Max){j = tag - 1;while(j > 0){if(Count[j].boat){cout << "送至左岸" << Count[j].monkLeft - Count[Count[j].parent].monkLeft << "个传道士和"<< Count[j].wildLeft - Count[Count[j].parent].wildLeft << "个野人,所以:左岸有"<< Count[j].monkLeft << "个传道士;" << Count[j].wildLeft << "个野人" << endl;}else{cout << "送至右岸" << Count[Count[j].parent].monkLeft - Count[j].monkLeft << "个传道士和"<< Count[Count[j].parent].wildLeft - Count[j].wildLeft << "个野人,所以:左岸有"<< Count[j].monkLeft << "个传道士;" << Count[j].wildLeft << "个野人" << endl;}j = Count[j].parent;}int a;cin>>a;}else{cout << "运送失败。
传教士和野人问题实验报告1.上机内容传教士与野人问题求解(宽度搜索算法)二二问题背景:从前有一条河,河的左岸有 m 个传教士(Missionary)和 m 个野人(Cannibal),和一艘最多可乘 n 人的小船。
约定左岸,右岸和船上或者没有传教士,或者野人数量少于传教士,否则野人会把传教士吃掉。
三三实验内容:编程,接收 m 和 n,搜索一条可让所有的野人和传教士安全渡到右岸的方案,例如下图: (M 表示传教士(Missionary),C 表示野人(Cannibal))初态目标 Left Bank River Right bankLeft Bank River Right bank M....M....C....C....注:本实验的举例均以 3 个传教士和 3 个野人同在左岸作为初始状态。
四四实验方案和算法:1 .数据结构:本实验需要用到的数据结构主要是队列和堆栈,其实现均包含于 dso.h 头文件中,分别命名为 class stack 和 class queue。
2 2 .宽度搜索算法:(1) 结点结构:class Move {public:int missionary;//要移动的传教士数量int cannibal;//野人}; class ElemType : Move {//继承 Move 类,获得传教士,野人数据成员。
private:bool boat;//船是否在左岸?public:ElemType_flag;// 标示前一状态即扩展出本结点的父结点信息ElemType(int MA__PEOPLE) {//创建初始状态missionary = cannibal = MA__PEOPLE;boat = true;flag = NULL;} ......在这里,Elemtype 集成了 Move,从而获得 Move 类的传教士和野人数据成员。
以上两个类的数据成员用于保存所有扩展生成的结点。
状态空间暗示法例:设N个布道士带着N个野人荡舟渡河,且为安然起见,渡河需遵循两个约束:〔1〕船上的人数不得超过载重限量,设为K个人;〔2〕为预防野人攻击,任何时刻〔包罗两岸、船上〕野人数目不得超过布道士数目。
应如何规划渡河方案?为便于理解状态空间暗示法,可简化该问题到一个特例:N=3,K=2。
解:首先拔取描述问题状态的方法。
在这个问题中,需要考虑两岸的修道士人数和野人数,还需要考虑船在左岸还是在右岸。
从而可用一个三元组来暗示状态S=(m, c, b)此中,m暗示左岸的修道士人数,c暗示左岸的野人数,b暗示左岸的船数。
右岸的状态可由下式确定:右岸修道士数m'=3-m右岸野人数c'=3-c右岸船数b'=1-b在这种暗示方式下,m和c都可取0、1、2、3中之一,b可取0和1中之一。
因此,共有4×4×2=32种状态。
这32种状态并非全有意义,除去不合法状态和修道士被野人吃掉的状态,有意义的状态只有16种:S0=(3, 3, 1) S1=(3, 2, 1) S2=(3, 1, 1) S3=(2, 2, 1)S4=(1, 1, 1) S5=(0, 3, 1) S6=(0, 2, 1) S7=(0, 1, 1)S8=(3, 2, 0) S9=(3, 1, 0) S10=(3, 0, 0) S11=(2, 2, 0)S12=(1, 1,0) S13=(0, 2, 0) S14=(0, 1, 0) S15=(0, 0, 0)有了这些状态,还需要考虑可进行的操作。
操作是指用船把修道士或野人从河的左岸运到右岸,或从河的右岸运到左岸。
每个操作都应当满足如下条件:一是船至少有一个人〔m或c〕操作,离开岸边的m和c的减少数目应该等于达到岸边的m和c的增加数目;二是每次操作船上人数不得超过2个;三是操作应包管不发生不法状态。
因此,操作应由条件局部和动作局部:条件:只有当其条件具备时才能使用动作:刻划了应用此操作所发生的成果。
第五章搜索策略习题参考解答5.1 练习题5.1 什么是搜索?有哪两大类不同的搜索方法?两者的区别是什么?5.2 用状态空间法表示问题时,什么是问题的解?求解过程的本质是什么?什么是最优解?最优解唯一吗?5.3 请写出状态空间图的一般搜索过程。
在搜索过程中OPEN表和CLOSE表的作用分别是什么?有何区别?5.4 什么是盲目搜索?主要有几种盲目搜索策略?5.5 宽度优先搜索与深度优先搜索有何不同?在何种情况下,宽度优先搜索优于深度优先搜索?在何种情况下,深度优先搜索优于宽度优先搜索?5.6 用深度优先搜索和宽度优先搜索分别求图5.10所示的迷宫出路。
图5.10 习题5.6的图5.7 修道士和野人问题。
设有3个修道士和3个野人来到河边,打算用一条船从河的左岸渡到河的右岸去。
但该船每次只能装载两个人,在任何岸边野人的数目都不得超过修道士的人数,否则修道士就会被野人吃掉。
假设野人服从任何一种过河安排,请使用状态空间搜索法,规划一使全部6人安全过河的方案。
(提示:应用状态空间表示和搜索方法时,可用(N m,N c)来表示状态描述,其中N m和N c分别为传教士和野人的人数。
初始状态为(3,3),而可能的中间状态为(0,1),(0,2),(0,3), (1,1),(2,1),(2,2),(3,0),(3,1),(3,2)等。
)5.8 用状态空间搜索法求解农夫、狐狸、鸡、小米问题。
农夫、狐狸、鸡、小米都在一条河的左岸,现在要把它们全部送到右岸去。
农夫有一条船,过河时,除农夫外,船上至多能载狐狸、鸡和小米中的一样。
狐狸要吃鸡,鸡要吃小米,除非农夫在那里。
试规划出一个确保全部安全的过河计划。
(提示:a.用四元组(农夫,狐狸,鸡,米)表示状态,其中每个元素都可为0或1,0表示在左岸,1表示在右岸;b.把每次过河的一种安排作为一个算符,每次过河都必须有农夫,因为只有他可以划船。
)5.9 设有三个大小不等的圆盘A 、B 、C 套在一根轴上,每个圆盘上都标有数字1、2、3、4,并且每个圆盘都可以独立地绕轴做逆时针转动,每次转动90°,初始状态S 0和目标状态S g 如图5.11所示,用宽度优先搜索法和深度优先搜索法求从S 0到S g 的路径。
传教士-野人问题有N个传教士和N个野人要过河,现在有一条船只能承载K个人(包括野人),K<N,在任何时刻,如果有野人和传教士在一起,必须要求传教士的人数多于或等于野人的人数。
设M为传教士的人数,C为野人的人数,用状态空间发求解此问题的过程如下:M、C = N,boat = k,要求M>=C且M+C <= K初始状态目标状态L R L RM 3 0 M 0 3C 3 0 C 0 3B 1 0 B 0 1(1)用三元组来表示(ML , CL , BL)其中0<=ML , CL <= 3 , BL ∈{ 0 , 1}(3 , 3 , 1) (0 , 0 , 0)(2)规则集合P10if ( ML ,CL , BL=1 ) then ( ML–1 , CL , BL –1 )P01if ( ML ,CL , BL=1 ) then ( ML , CL–1 , BL –1 )P11if ( ML ,CL , BL=1 ) then ( ML–1 , CL–1 , BL –1 )P20if ( ML ,CL , BL=1 ) then ( ML–2 , CL , BL –1 )P02if ( ML ,CL , BL=1 ) then ( ML , CL–2 , BL –1 )Q10if ( ML ,CL , BL=0 ) then ( ML+1 , CL , BL+1 )Q01if ( ML ,CL , BL=0 ) then ( ML , CL+1 , BL +1 )Q11if ( ML ,CL , BL=0 ) then ( ML+1 , CL +1, BL +1 )Q20 if ( ML ,CL , BL=0 ) then ( ML+2 , CL +2, BL +1 )Q02if ( ML ,CL , BL=0 ) then ( ML , CL +2, BL +1 )(3)寻找一个启发式函数引导规则的选用右岸总人数6 – ML – CL 两岸中传教士数目>=野人数目f =–∞其它f=3 Q 01f=2 P 02 f=1 Q 01f=1 Q 11f=1 P 01 f=2 P 11 (3,3,1) (3,2,0)(2,2,0) (3,1,0) (3,2,1) (3,0,0) f=3 P 02(3,1,1) f=2 Q 01(1,1,0) f=4 P 20(2,2,1) f=2 Q 11(1,1,0) f=4 P 20(2,2,1) f=2 Q 11(0,2,0) f=4 P 20(0,3,1)f=3 Q 01(0,1,1)f=5 P 02(0,2,1) f=4 Q 01 (0,0,0)f=3 Q 01(1,1,1) f=4 Q 106.2.3 用状态空间法求解传教士和食人者问题例6-2 传教士和食人者问题(The Missionaries and Cannibals Problem)。
传教士野人课程设计一、课程目标知识目标:1. 学生能理解并掌握传教士与野人故事的历史背景,了解文化冲突与交流的重要知识点。
2. 学生能够分析并描述传教士与野人之间的交流方式及其影响。
3. 学生能掌握相关的历史事件,并能够将其与当今跨文化交流进行对比。
技能目标:1. 学生通过研究传教士与野人的交流方式,提升自己的观察、分析、整合信息的能力。
2. 学生通过小组讨论,提高沟通与协作能力,学会尊重不同文化背景下的观点。
3. 学生能够运用所学知识,创作有关传教士与野人交流的故事或短剧,提升表达和创造能力。
情感态度价值观目标:1. 学生培养对历史文化的尊重与兴趣,认识到不同文化之间交流的重要性。
2. 学生通过学习传教士与野人的交流,学会理解和尊重不同的生活方式与价值观。
3. 学生能够树立开放、包容的世界观,认识到多元文化背景下的共同点与差异,培养国际视野。
课程性质:本课程为历史与社会学科相结合的跨学科课程,旨在通过具体案例的分析,使学生理解文化差异与交流的重要性。
学生特点:考虑到学生所在年级的特点,他们对历史事件有一定的了解,但跨文化交流的概念可能较为陌生。
因此,课程将采用生动形象的故事和案例,激发学生兴趣,引导他们深入思考。
教学要求:教师应注重培养学生的学习兴趣,引导学生主动参与课堂讨论,鼓励他们提出自己的观点,从而实现课程目标。
同时,教师需关注学生的学习成果,确保课程目标的达成。
二、教学内容本课程依据课程目标,结合教材内容,设计以下教学大纲:1. 导入新课:通过引入传教士与野人的故事,激发学生对文化冲突与交流的兴趣。
教材章节:《文化交流与冲突》2. 传教士与野人历史背景介绍:讲解传教士东来、新航路开辟等历史事件,分析文化差异产生的原因。
教材章节:《宗教传播与文化交流》3. 传教士与野人交流案例分析:选取具有代表性的案例,如耶稣会士与印第安人的交流,分析交流过程中的冲突与融合。
教材章节:《文化交流的案例分析》4. 小组讨论:分组讨论传教士与野人交流的意义,探讨如何尊重和包容不同的文化。
修道士与野人问题6.修道士与野人问题这是一个古典问题。
假设有n个修道士和n个野人准备渡河,但只有一条能容纳c人的小船,为了防止野人侵犯修道士,要求无论在何处,修道士的个数不得少于野人的人数(除非修道士个数为0)。
如果两种人都会划船,试设计一个算法,确定他们能否渡过河去,若能,则给出一个小船来回次数最少的最佳方案。
要求:(1)用一个三元组(x1,x2,x3)表示渡河过程中各个状态。
其中,x1表示起始岸上修道士个数,x2表示起始岸上野人个数,x3表示小船位置(0——在目的岸,1——在起始岸)。
例如(2,1,1)表示起始岸上有两个修道士,一个野人,小船在起始岸一边。
采用邻接表做为存储结构,将各种状态之间的迁移图保存下来。
(2)采用广度搜索法,得到首先搜索到的边数最少的一条通路。
(3)输出数据若问题有解(能渡过河去),则输出一个最佳方案。
用三元组表示渡河过程中的状态,并用箭头指出这些状态之间的迁移:目的状态←…中间状态←…初始状态。
若问题无解,则给出“渡河失败”的信息。
(4)求出所有的解。
1.需求分析有n个修道士和n个野人准备渡河,但只有一条能容纳c人的小船,为了防止野人侵犯修道士,要求无论在何处,修道士的个数不得少于野人的人数,否则修道士就会有危险,设计一个算法,确定他们能否渡过河去,若能,则给出一个小船来回次数最少的最佳方案。
用三元组(x1,x2,x3)来表示渡河过程中各个状态,其中,x1表示起始岸上修道士个数,x2表示起始岸上野人个数,x3表示小船位置(0——在目的岸,1——在起始岸)。
若问题有解(能渡过河去),则输出一个最佳方案。
用三元组表示渡河过程中的状态,并用箭头指出这些状态之间的迁移:目的状态←…中间状态←…初始状态,若问题无解,则给出“渡河失败”的信息。
2.设计2.1 设计思想(1)数据结构设计逻辑结构设计: 图型结构存储结构设计: 链式存储结构采用这种数据结构的好处:便于采用广度搜索法,得到首先搜索到的边数最少的一条通路,输出一个最佳方案,采用图的邻接表存储结构搜索效率较高。
(2)算法设计算法设计的总体设计思路为:在得到修道士人数和小船的容纳人数后,用boatcase得到所有情况,然后再进行安全性检查,以减去修道士少于野人的情况,接着用孩子兄弟结点表示法,将去对面的路作为孩子结点,路与路是兄弟关系,到达另一边时,同样以这种方法,直到找到(0,0,0)。
主要分为4个模块:boatcase生成所有情况,BFS得到边数最少的最佳方案,safe安全性检测,print输出安全渡河的全过程。
各个模块要完成的主要功能分别为:生成模块:生成所有的可能渡河情况安全检测模块:对所有的可能渡河情况进行安全检测,,以减去修道士少于野人的情况广度搜索模块:采用广度搜索法,得到首先搜索到的边数最少的一条通路输出模块:输出所有安全渡河的全过程主程序的流程图:来进行初始化来插入结点2.2 设计表示(1)函数调用关系图(2)函数接口规格说明void Linkinit(Link **head)void insertson(Link *head, DataType x) void insertbro(Link *head,DataType x)int boatcase(DataType x,int n)void guangdu(Link *p,int n,int c)int safe(DataType x,int n)void print(Link *q,Link *p)2.3 详细设计➢生成模块int boatcase(DataType x,int n) {int i=0,a,b,t=0;if(x.cw) {a=0;b=n-a;while (a+b>=1){t++;while (b>=0){ array[i].xds=a;array[i].yr=b;i++;a++;b--;}a=0; b=n-a-t;}}else{a=1;b=0;t=0;while (a+b<=n){t++;while (a>=0){array[i].xds=a*(-1);array[i].yr=b*(-1);i++;a--;b++;}a=array[0].xds*(-1)+t;b=0;}}return i;}➢安全检测模块int safe(DataType x,int n){if((x.xds>=x.yr||x.xds==0)&&((n-x.xds)>=(n-x.yr)||x.xds==n)&&x.xds>=0&&x.xds<=n&&x.yr>=0&&x.yr<=n) return 1;elsereturn 0;}➢广度搜索模块void guangdu(Link *p,int n,int c){Link *q,*t;DataType tem;int i,flag1,flag2,g=0,j,count=0;q=p->son;while (q!=NULL)/{flag1=0;j=boatcase(q->data,c);for (i=0;i<j;i++) {tem.xds=q->data.xds-array[i].xds;tem.yr=q->data.yr-array[i].yr;tem.cw=1-q->data.cw;t=q;if (safe(tem,n)) {flag2=1;//1while (t!=p){if(tem.xds== t->data.xds&&tem.yr==t->data.yr&&tem.cw==t->data.cw){flag2=0;break;}t=t->par;}if(flag2==1){if (flag1==0){insertson(q, tem);flag1=1;}elseinsertbro(q,tem); if (tem.xds==0&&tem.yr==0&&tem.cw==0){print(q,p);count++;}}}}q=q->next;}if (count==0)printf("无法成功渡河!\n");elseprintf("有%d种渡河方式。
\n",count);}➢输出模块void print(Link *q,Link *p){DataType a[100];int i=1;a[0].cw=0;a[0].xds=0;a[0].yr=0;while (q!=p){a[i++]=q->data;q=q->par;}while ((--i)>-1){printf("( %d %d %d )",a[i].xds,a[i].yr,a[i].cw);if (!(a[i].xds==0&&a[i].yr==0&&a[i].cw==0)){if(a[i].cw==1)printf("-->(%d %d)-->(%d %d 0)\n",a[i].xds-a[i-1].xds,a[i].yr-a[i-1].yr,a[i-1].xds,a[i-1].yr);elseprintf(" <-- ( %d %d ) <-- ( %d %d1 )\n",(a[i].xds-a[i-1].xds)*(-1),(-1)*(a[i].yr-a[i-1].yr),a[i-1].xds,a[i-1].yr);}}printf("渡河成功!\n");}3.调试分析(1)本题是采用邻接表做为存储结构,将各种状态之间的迁移图保存下来,并用孩子兄弟表示法,以实现广度搜索;刚编好程序时出现死循环的现象,例如:带过去2个野人又带回来2个野人,在和其他同学讨论后,采用了2个标志位来避免出现死循环的现象,在进行运行的时候,曾出现了打印输出错误,经过一步一步调试,发现在插入结点的时候出现了插入错误,即没有考虑到pre 的改变,通过改正,重新运行检测,运行结果正确,在排版时通过一步步调试,参考了课本和老师的课件,并与和其他同学讨论后,终于通过调试和改正,,能够使输出结果很明显的渡河方案。
(2)可改进内容:显示表示哪些是渡河次数最短的,最佳渡河方案一共有几种,并输出每种最佳渡河方案,另外,可尝试用深度优先搜索算法来找最佳方案。
4.用户手册本程序在VC++6.0环境下运行,根据提示输入相应的渡河人数和小船能容纳的人数即可。
5.测试数据及测试结果测试用例1测试输入: n=3,c=2测试目的:检验程序运行时是否会陷入死循环正确输出:见截屏1,2实际输出:见截屏 3,4错误原因:未正确设置标志位,出现死循环现象当前状态:已改正截屏1截屏2截屏3截屏46.源程序清单#include <stdio.h>#include <malloc.h>#include <stdlib.h>typedef struct{int xds; //修道士个数int yr; //野人个数int cw; //船的位置}DataType;DataType array[50000];typedef struct node//结构体定义{DataType data;struct node *son;//儿子struct node *bro;//兄弟struct node *par;//双亲struct node *next;}Link;void Linkinit(Link **head) //初始化操作{*head=(Link *)malloc(sizeof (Link)); //申请动态空间(*head)->son=NULL;(*head)->bro=NULL;(*head)->par=NULL;(*head)->next=NULL;}void insertson(Link *head, DataType x) //在邻接表中插入儿子结点的操作{Link *q,*s;q=(Link *)malloc(sizeof (Link));q->data=x;head->son=q;//将x插入给头结点的儿子指针s=head;while (s->next!=NULL)s=s->next;q->par=head;q->son=NULL;q->bro=NULL;s->next=q;q->next=NULL;}void insertbro(Link *head,DataType x)//在邻接表中插入兄弟结点的操作, //所有的兄弟结点都指向他们右边的结点{Link *q,*s;q=(Link *)malloc(sizeof (Link));s=head->son;q->data=x;while (s->bro!=NULL)s=s->bro;s->bro=q;s->next=q;q->next=NULL;q->bro=NULL;q->par=head;q->son=NULL;}int boatcase(DataType x,int n) //生成所有情况;{int i=0,a,b,t=0;if(x.cw) //在此岸,上船的人多优先{a=0;b=n-a; //a为修道士b为野人while (a+b>=1)//当船上有人时{t++;while (b>=0)//当野人个数不为负数{array[i].xds=a;array[i].yr=b;i++;a++;b--;}a=0;//船上空位个数b=n-a-t;}}else//在对岸,上船的人少优先{a=1;b=0;t=0;while (a+b<=n){t++;//船上的人数while (a>=0){array[i].xds=a*(-1);array[i].yr=b*(-1);i++;a--;b++;}a=array[0].xds*(-1)+t;b=0;}}return i; //i为总数量}int safe(DataType x,int n)//安全性检测{ // 起始目的if ((x.xds>=x.yr||x.xds==0)&&((n-x.xds)>=(n-x.yr)||x.xds==n)&&x.xds>=0&&x.xds<=n&&x.yr>=0&&x.yr<=n)return 1;//船上修道士elsereturn 0;}void print(Link *q,Link *p) //打印安全渡河的过程,当船到对岸时,把对岸当作其始岸,此岸当作彼岸{DataType a[100];int i=1;a[0].cw=0;a[0].xds=0;a[0].yr=0;while (q!=p)//避免出现相同情况而循环{a[i++]=q->data;//将一次过河的情况给b[i]q=q->par;}while ((--i)>-1) //输出过河图{printf("( %d %d %d )",a[i].xds,a[i].yr,a[i].cw);if (!(a[i].xds==0&&a[i].yr==0&&a[i].cw==0)){if(a[i].cw==1)printf("-->(%d %d)-->(%d %d 0)\n",a[i].xds-a[i-1].xds,a[i].yr-a[i-1].yr,a[i-1].xds,a[i-1].yr);//a[i].xds-a[i-1].xds表示过河过程中船上的修道士数,a[i].yr-a[i-1].yr表示过河过程中船上的野人数elseprintf(" <-- ( %d %d ) <-- ( %d %d1 )\n",(a[i].xds-a[i-1].xds)*(-1),(-1)*(a[i].yr-a[i-1].yr),a[i-1].xds,a[i-1].yr);}}printf("渡河成功!\n");}void guangdu(Link *p,int n,int c)//广度搜索{Link *q,*t;DataType tem;int i,flag1,flag2,g=0,j,count=0;q=p->son;while (q!=NULL)//逐个搜索儿子结点{flag1=0;//等于0表示插入儿子结点,1表示插入兄弟结点j=boatcase(q->data,c);//可能过河的情况for (i=0;i<j;i++)//搜索兄弟结点{tem.xds=q->data.xds-array[i].xds;tem.yr=q->data.yr-array[i].yr;tem.cw=1-q->data.cw;t=q;if (safe(tem,n))//是否安全{flag2=1;//1表示没有死循环while (t!=p)//保证不会出现循环{if(tem.xds== t->data.xds&&tem.yr==t->data.yr&&tem.cw==t->data.cw){//出现相当情况时候flag2=0;break;}t=t->par;}if(flag2==1){if (flag1==0)//插入儿子结点{insertson(q, tem);flag1=1;}else//插入兄弟结点insertbro(q,tem); if (tem.xds==0&&tem.yr==0&&tem.cw==0){print(q,p);count++;}}}}q=q->next;}if (count==0)printf("无法成功渡河!\n");elseprintf("有%d种渡河方式。