MC牧师过河问题
传教士野人过河问题-两种解法思路
实验 传教士野人过河问题37030602 王世婷一、实验问题传教士和食人者问题(The Missionaries and Cannibals Problem )。
在河的左岸有3个传教士、1条船和3个食人者,传教士们想用这条船将所有的成员运过河去,但是受到以下条件的限制:(1)传教士和食人者都会划船,但船一次最多只能装运两个;(2)在任何岸边食人者数目都不得超过传教士,否则传教士就会遭遇危险:被食人者攻击甚至被吃掉。
此外,假定食人者会服从任何一种过河安排,试规划出一个确保全部成员安全过河的计划。
二、解答步骤(1) 设置状态变量并确定值域M 为传教士人数,C 为野人人数,B 为船数,要求M>=C 且M+C <= 3,L 表示左岸,R 表示右岸。
初始状态 目标状态L R L RM 3 0 M 0 3C 3 0 C 0 3B 1 0 B 0 1(2) 确定状态组,分别列出初始状态集和目标状态集用三元组来表示f S :(ML , CL , BL )(均为左岸状态)其中03,03ML CL ≤≤≤≤,BL ∈{ 0 , 1}0S :(3 , 3 , 1) g S : (0 , 0 , 0)初始状态表示全部成员在河的的左岸;目标状态表示全部成员从河的左岸全部渡河完毕。
(3) 定义并确定规则集合仍然以河的左岸为基点来考虑,把船从左岸划向右岸定义为Pij 操作。
其中,第一下标i 表示船载的传教士数,第二下标j 表示船载的食人者数;同理,从右岸将船划回左岸称之为Qij 操作,下标的定义同前。
则共有10种操作,操作集为F={P01,P10,P11,P02,P20,Q01,Q10,Q11,Q02,Q20}P 10 if ( ML ,CL , BL=1 ) then ( ML –1 , CL , BL –1 )P 01 if ( ML ,CL , BL=1 ) then ( ML , CL –1 , BL –1 )P 11 if ( ML ,CL , BL=1 ) then ( ML –1 , CL –1 , BL –1 )P 20 if ( ML ,CL , BL=1 ) then ( ML –2 , CL , BL –1 )P 02 if ( ML ,CL , BL=1 ) then ( ML , CL –2 , BL –1 )Q 10 if ( ML ,CL , BL=0 ) then ( ML+1 , CL , BL+1 )Q 01 if ( ML ,CL , BL=0 ) then ( ML , CL+1 , BL +1 )Q 11 if ( 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 )(4)当状态数量不是很大时,画出合理的状态空间图图1 状态空间图箭头旁边所标的数字表示了P或Q操作的下标,即分别表示船载的传教士数和食人者数。
C实现传教士与野人过河问题实验报告
传教士与野人过河问题实验报告1 问题定义河的两岸有三个传教士和三个野人需要过河,目前只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于传教士的人数,那么传教士就会被野人攻击,怎么找出一种安全的渡河方案呢?2 算法分析首先,先来看看问题的初始状态和目标状态,定义河的两岸分别为左岸和右岸,设定状态集合为(左岸传教士人数,右岸野人数,右岸传教士人数,右岸野人数,船的位置),船的位置:-1表示船在左岸,1表示船在右岸。
初始状态:(3,3,0,0,0,-1)目标状态:(0,0,3,3,1)然后,整个问题就抽象成了怎样从初始状态经中间的一系列状态达到目标状态。
问题状态的改变是通过划船渡河来引发的,所以合理的渡河操作就成了通常所说的算符,根据题目要求,可以得出以下5个算符(按照渡船方向的不同,也可以理解为10个算符):渡1野人、渡1传教士、渡1野人1传教士、渡2野人、渡2传教士根据船的位置,向左移或向右移通过递归依次执行5种算符,判断是否找到所求,并排除不符合实际的状态,就可以找到所有可能的解,如图1所示为递归函数流程图。
数据结构方面采用如下所示的结构体存储当前传教士、野人、船三者的状态。
struct riverSides {int churchL;//左岸传教士数int wildL;//左岸野人数int churchR; //右岸传教士数int wildR; //右岸野人数int boat;//船的位置,-1在左岸,1在右岸};图 1 传教士与野人过河递归函数流程图3 编程实现程序使用C++实现,具体代码如下:#include<iostream>#include<vector>#include<string>using namespace std;struct riverSides{int churchL;//左岸传教士数int wildL;//左岸野人数int churchR; //右岸传教士数int wildR; //右岸野人数int boat;//船的位置,-1在左岸,1在右岸};int mycount = 0;//统计成功过河次数int CvsWdfs(riverSides lastcurrentState, vector <riverSides> lastParameters, vector<string> operation, int ifboacurrentStatety){if (lastcurrentState.churchR == 3 && lastcurrentState.wildR == 3){mycount++;cout << "第" << mycount << "次成功过河" << endl;cout << "传教士野人 | 移动方向" << endl;for (int i = 0; i < operation.size(); i++){cout << operation[i] << endl;}cout << endl;return 0;}//判断过河操作否重复,去除死循环for (int i = 0; i < lastParameters.size() - 1; i++){if (lastParameters[i].wildL == lastcurrentState.wildL&&lastParameters[i].churchL == lastcurrentState.churchL){if (lastcurrentState.boat == lastParameters[i].boat)return 0;}}//检验人数数据合法性if (lastcurrentState.churchL < 0 || lastcurrentState.wildL < 0 || lastcurrentState.churchR < 0 || lastcurrentState.wildR < 0)return 0;//传教士是否被吃if ((lastcurrentState.churchL < lastcurrentState.wildL&&lastcurrentState.churchL != 0) || (lastcurrentState.churchR < lastcurrentState.wildR&&lastcurrentState.churchR != 0)) return 0;//递归执行五类过河操作,boat=-1船在左岸,boat=1船在右岸,传入boat为上一次船位置//下次应当取反riverSides currentState;//两个传教士过河if (lastcurrentState.boat == 1)operation.push_back(" 2 0 | 左岸->右岸");elseoperation.push_back(" 2 0 | 右岸->左岸");currentState.churchL = lastcurrentState.churchL - 2 * lastcurrentState.boat;currentState.wildL = lastcurrentState.wildL;currentState.churchR = lastcurrentState.churchR + 2 * lastcurrentState.boat;currentState.wildR = lastcurrentState.wildR;currentState.boat = -lastcurrentState.boat;lastParameters.push_back(currentState);CvsWdfs(currentState, lastParameters,operation, 0);operation.pop_back();lastParameters.pop_back();//两个野人过河if (lastcurrentState.boat == 1)operation.push_back(" 0 2 | 左岸->右岸");elseoperation.push_back(" 0 2 | 右岸->左岸");currentState.churchL = lastcurrentState.churchL;currentState.wildL = lastcurrentState.wildL - 2 * lastcurrentState.boat;currentState.churchR = lastcurrentState.churchR;currentState.wildR = lastcurrentState.wildR + 2 * lastcurrentState.boat;currentState.boat = -lastcurrentState.boat;lastParameters.push_back(currentState);CvsWdfs(currentState, lastParameters, operation, 0);lastParameters.pop_back();operation.pop_back();//一个野人,一个传教士if (lastcurrentState.boat == 1)operation.push_back(" 1 1 | 左岸->右岸");elseoperation.push_back(" 1 1 | 右岸->左岸");currentState.churchL = lastcurrentState.churchL - 1 * lastcurrentState.boat;currentState.wildL = lastcurrentState.wildL - 1 * lastcurrentState.boat;currentState.churchR = lastcurrentState.churchR + 1 * lastcurrentState.boat;currentState.wildR = lastcurrentState.wildR + 1 * lastcurrentState.boat;currentState.boat = -lastcurrentState.boat;lastParameters.push_back(currentState);CvsWdfs(currentState, lastParameters,operation, 0);operation.pop_back();lastParameters.pop_back();//一个传教士过河if (lastcurrentState.boat == 1)operation.push_back(" 1 0 | 左岸->右岸");elseoperation.push_back(" 1 0 | 右岸->左岸");currentState.churchL = lastcurrentState.churchL - 1 * lastcurrentState.boat;currentState.wildL = lastcurrentState.wildL;currentState.churchR = lastcurrentState.churchR + 1 * lastcurrentState.boat;currentState.wildR = lastcurrentState.wildR;currentState.boat = -lastcurrentState.boat;lastParameters.push_back(currentState);CvsWdfs(currentState, lastParameters, operation, 0);operation.pop_back();lastParameters.pop_back();//一个野人过河if (lastcurrentState.boat == 1)operation.push_back(" 0 1 | 左岸->右岸");elseoperation.push_back(" 0 1 | 右岸->左岸");currentState.churchL = lastcurrentState.churchL;currentState.wildL = lastcurrentState.wildL - 1 * lastcurrentState.boat;currentState.churchR = lastcurrentState.churchR;currentState.wildR = lastcurrentState.wildR + 1 * lastcurrentState.boat;currentState.boat = -lastcurrentState.boat;lastParameters.push_back(currentState);CvsWdfs(currentState, lastParameters, operation, 0);operation.pop_back();lastParameters.pop_back();return 0;}int main(){int churchL = 3, wildL = 3, churchR = 0, wildR = 0;//分别用来计算左岸和右岸的传教士和野人vector <riverSides> lastParameters;//保存每一步移动操作的两岸传教士、野人人数vector <string> operation;//保存当前操作的描述//初始化左岸参数,可以认为是从右岸移动至左岸的操作//boat=-1 表示船在左岸,boat=1表示船在右岸riverSides currentState;currentState.churchL = 3;currentState.wildL = 3;currentState.churchR = 0;currentState.wildR = 0;currentState.boat = 1;lastParameters.push_back(currentState);CvsWdfs(currentState, lastParameters,operation, 0);lastParameters.pop_back();system("pause");return 0;}4 程序结果最终得到如图2、3所示的四种过河方式。
算法_精品文档
一、算法的定义
有三个牧师和三个野人过河,只有一条能装下 两个人的船,在河的任何一方或者船上,如果野人 的人数大于牧师的人数,那么牧师就会有危险(被 野人吃掉)。你能找出一种安全的渡河方案吗?请 记录详细的方法和步骤!
第一步:两个野人划船到B岸 一个野人划船回到A岸
第二步:两个野人划船到B岸 一个野人划船回到A岸
请大家把书本打开翻到68页,快速浏览 本页的内容。
流程图的常用符号
起止框;输入输出框;处理框;判断框;流程线。
图形符号
名称
说明
起止框 算法的开始或结束
输入输出框 输入和输出数据
处理框 指出要处理的内容
判断框 条件判断及产生分支的情况
流程线 从一个步骤到下一个步骤
五、程序的三种基本结构
顺序结构 早晨起床
第二步:在含有假币的那组金币中任意取2枚分别放在天平两边,若平衡,则剩下 的那枚是假币;若不平衡,较轻的那枚是假币。
自然语言表示
开始 将9枚金币平均分成3组
任取其中2组分别放在天平两边
Y
N
是否平衡?
输出Y 结束
假币在剩下的那组中
任取其中2枚分别放在天平两边
Y
N
是否平衡?
假币在较轻的那组中
三、算法的表示形式
请设计一个算法,求键盘输入两数之和并输出结果。
自然语言
用键盘先输入一个数, 再输入另一个数, 计算两数和, 输出“和”的结果。
流程图
开始 输入一个加数 输入另一个加数 计算两数之和
输出和 结束
计算机语言
Private Sub Command1_Click()
a = Val(Text1.Text) b = Val(Text2.Text) sum = a + b Print sum End Sub
传教士(牧师)与野人问题-模拟人工智能实验_CSDN博客_传教士与野人问题
传教士(牧师)与野人问题-模拟人工智能实验_结缘缘的博客-CSDN博客_传教士与野人问题题目有n个牧师和n个野人准备渡河但只有一条能容纳c个人的小船为了防止野人侵犯牧师要求无论在何处牧师的人数不得少于野人的人数(除非牧师人数为0) 且假定野人与牧师都会划船试设计一个算法确定他们能否渡过河去若能则给出小船来回次数最少的最佳方案。
实验步骤输入牧师人数(即野人人数) n 小船一次最多载人量c。
输出若问题无解则显示Failed 否则显示Successed输出所有可行方案并标注哪一组是最佳方案。
用三元组(X1, X2, X3)表示渡河过程中的状态。
并用箭头连接相邻状态以表示迁移过程初始状态- 中间状态- 目标状态。
例当输入n 2 c 2时输出221- 200- 211- 010- 021- 000 其中X1表示起始岸上的牧师人数X2表示起始岸上的野人人数X3表示小船现在位置(1表示起始岸0表示目的岸)。
要求写出算法的设计思想和源程序并有用户界面实现人机交互控制台或者窗口都可以进行输入和输出结果如Please input n: 2 Please input c: 2 Optimal Procedure: 221- 200- 211- 010- 021- 000Successed or Failed?: Successed实现代码#include stdio.h #include iostream #include stdlib.h using namespace std;struct State { int Lsavage; int Lgodfather; int Rsavage; int Rgodfather; int boat; //boat at left 0 ; boat at right struct State *States new State[150];struct routesave { int savage; int godfather;struct routesave* routesaves new routesave[150];int godfather, savage, boatnum;void init(State m) { cout 请输入野人和牧师的人数n 以及船的最大载量c endl; int n, c; cin n c; m.Rgodfather n; m.Rsavage n; godfather n, savage n; boatnum c; m.Lgodfather m.Lsavage 0; m.boat 1;void boaloading(int i, int s, int g) { //s个野人和g个传教士if (States[i].boat 0) { routesaves[i].savage s*-1; //左边到右边是负数个野人routesaves[i].godfather g * -1; //左边到右边负数个传教士States[i 1].LsavageStates[i].Lsavage - s; States[i 1].Lgodfather States[i].Lgodfather - g; States[i 1].Rsavage States[i].Rsavage s; States[i 1].Rgodfather States[i].Rgodfather g; States[i 1].boat 1; else{ routesaves[i].savage s; //右边到左边是正数个野人routesaves[i].godfather g; //右边到左边正数个传教士States[i 1].Rsavage States[i].Rsavage-s; States[i 1].RgodfatherStates[i].Rgodfather - g; States[i 1].Lsavage States[i].Lsavage s; States[i 1].Lgodfather States[i].Lgodfather g; States[i 1].boat0;bool checkState(State m) { if (m.Rgodfather 0 m.Rgodfather m.Rsavage) return false; if (m.Lgodfather 0 m.Lgodfatherm.Lsavage) return false; else return true;void showSolution(int i) { cout 问题解决解决路径为endl; for (int c 0; c i; c ) { if (routesaves[c].savage 0) cout 第c 1 步routesaves[c].savage 个野人和routesaves[c].godfather 个传教士乘船去左边endl; else cout 第c 1 步routesaves[c].savage * -1 个野人和routesaves[c].godfather * -1 个传教士乘船去有右边endl; void nextstep(int i) { int c; if (i 150) cout 试探路径过大无法计算; exit(0); for (c 0; c i; c ) /*if the current state is same to previous,retrospect*/ if (States[c].Lsavage States[i].Lsavage States[c].Lgodfather States[i].Lgodfather States[c].Rsavage States[i].Rsavage States[c].Rgodfather States[i].Rgodfather States[c].boat States[i].boat) goto a; if (States[i].Rsavage 0 States[i].Rgodfather 0 States[i].boat 0) { showSolution(i); exit(0); if (States[i].boat 1) { //船在右边for (int s 1; s boatnum s States[i].Rsavage; s ) {//g 0 int g 0; boaloading(i, s, g); if (checkState(States[i 1])) { nextstep(i 1); for (int g 1; g boatnum g States[i].Rgodfather; g ) { //g! 0 for (int s 0; s boatnum - g s States[i].Rsavage s g; s ) { boaloading(i, s, g); if(checkState(States[i 1])) { nextstep(i 1); if (States[i].boat 0) { //船在左边for (int s 1; s boatnum s States[i].Lsavage; s ) {//g 0int g 0; boaloading(i, s, g); if (checkState(States[i 1])) { nextstep(i 1); for (int g 1; g boatnum g States[i].Lgodfather; g ) { //g! 0 for (int s 0; s boatnum - g s States[i].Lsavage s g; s ) { boaloading(i, s, g); if (checkState(States[i 1])) { nextstep(i 1);a:return;void main() { init(States[0]); nextstep(0);实验结果展示。
逻辑思维能力测试题
选择题:1、选出不同类的一项:A、蛇B、大树C、老虎2、在下列分数中,选出不同类的一项:A 3/5 B 3/7 C 3/93、男孩对男子,正如女孩对A青年B孩子C夫人D姑娘E妇女4、如果笔相对于写字,那么书相对于A娱乐B阅读C学文化D解除疲劳5、马之于马厩,正如人之于A牛棚B马车C房屋D农场E楼房6、2 8 14 20 ()请写出“ ()”处的数字。
7、下列四个词是否可以组成一个正确的句子生活水里鱼在 A 是B否8、下列六个词是否可以组成一个正确的句子球棒的用来是棒球打A是B否9、动物学家与社会学家相对应,正如动物与()相对A人类B问题C社会D社会学10、如果所有的妇女都有大衣,那么漂亮的妇女会有A更多的大衣B时髦的大衣C 大衣D昂贵的大衣11、1 3 2 4 6 5 7 (),请写出“ ()”处的数字12、南之于西北,正如西之于:A西北B东北C西南D东南13、找出不同类的一项A铁锅B小勺C米饭D碟子14、9 7 8 6 7 5 (),请写出“ ()”处的数字15、找出不同类的一项:A写字台B沙发C电视D桌布16、961 (25)432 932 ()731 ,请写出()内的数字17、选项ABCD中,哪一个应该填在“XOOOOXXOOOXXX”后面AXOO BOO COOX DOXX18、望子成龙的家长往往()苗助长A揠B堰C偃19、填上空缺的词:金黄的头发(黄山)刀山火海赞美人生()卫国战争20、选出不同类的一项:A地板B壁橱C窗户D窗帘21、1 8 27 (),请写出()内的数字。
22、填上空缺的词:罄竹难书(书法)无法无天作奸犯科()教学相长23、在括号内填上一个字,使其与括号前的字组成一个词,同时又与括号后的字也能组成一个词:款()样24、填入空缺的数字:16(96)12 10()7.525找出不同类的一项:A斑马B军马C赛马D骏马E驸马26、在括号上填上一个字,使其与括号前的字组成一个词,同时又与括号后的字也能组成一个词:祭()定27、在括号内填上一个字,使之既有前一个词的意思,又可以与后一个词组成词组:头部()震荡28、填入空缺的数字65 37 17 ()29、填入空缺的数字41(28)27 83()6530、填上空缺的字母CFI DHL EJ()参考答案:1、B;2、C;3、E;4、B;5、C;6、26;7、A;8、B;9、A;10、C;11、9;12、B;13、C;14、6;15、D;16、38;17、B;18、A;19、美国;20、D;21、58;22、科学;23、式;24、60;25、E;26、奠;27、脑;28、5;29、36;30、O.判断题:1大象是动物,动物有腿。
MC牧师过河问题
MC牧师过河问题⼈⼯智能上机实验报告学号:姓名:所在系:信息学院班级:实验名称:实验⽇期2016年12⽉3⽇实验指导教师实验机房A401------------------------------------------------------------------------------------------------------ 1.实验⽬的:(1)在掌握状态空间搜索策略的基础上,理解知识表⽰的⽅法。
(2)能够应⽤知识表⽰⽅法,解决实际问题2. 实验内容:(1)M-C问题描述有n个牧师和n个野⼈准备渡河,但只有⼀条能容纳c个⼈的⼩船,为了防⽌野⼈侵犯牧师,要求⽆论在何处,牧师的⼈数不得少于野⼈的⼈数(除⾮牧师⼈数为0),且假定野⼈与牧师都会划船,试设计⼀个算法,确定他们能否渡过河去,若能,则给出⼩船来回次数最少的最佳⽅案。
3.算法设计(编程思路或流程图或源代码)#include#include#include#define maxloop 100 /* 最⼤层数,对于不同的扩展⽅法⾃动调整取值*/#define pristnum 3 /*初始化时设定有3个野⼈3个牧师,实际可以改动*/#define slavenum 3struct SPQ{ int sr,pr; /* 船运⾏⼀个来回后河右岸的野⼈、牧师的⼈数*/int sl,pl; /* 船运⾏⼀个来回后河左岸的野⼈、牧师的⼈数*/int ssr,spr; /* 回来(由左向右时)船上的⼈数*/int sst,spt; /* 去时(由右向左时)船上的⼈数*/int loop; /* 本结点所在的层数*/struct SPQ *upnode ,*nextnode;/* 本结点的⽗结点和同层的下⼀个结点的地址*/}spq;int loopnum;/* 记录总的扩展次数*/int openednum;/* 记录已扩展节点个数*/int unopenednum;/* 记录待扩展节点个数*/int resultnum;struct SPQ *opened;struct SPQ *oend;struct SPQ *unopened;struct SPQ *uend;struct SPQ *result;void initiate();void releasemem();void showresult();void addtoopened(struct SPQ *ntx);int search();void goon();int stretch(struct SPQ* ntx);void recorder();void addtoopened(struct SPQ *ntx) /*扩展节点*/ { unopened = unopened -> nextnode; unopenednum--; if (openednum == 0 )oend = opened = ntx;oend -> nextnode = ntx;oend = ntx;openednum++;}void recorder(){int i , loop;struct SPQ *newnode;struct SPQ *ntx;loop = oend -> loop;ntx = oend;resultnum = 0;for( i = 0 ; i <= loop ; i++ ){newnode = (struct SPQ*) malloc (sizeof(spq));if(newnode==NULL){printf("\n内存不够!\n");exit(0);}newnode -> sr = ntx -> sr;newnode -> pr = ntx -> pr;newnode -> sl = ntx -> sl;newnode -> pl = ntx -> pl;newnode -> sst = ntx -> sst;newnode -> spt = ntx -> spt; newnode -> ssr = ntx -> ssr; newnode -> spr = ntx -> spr; newnode -> nextnode = NULL;ntx = ntx -> upnode;if(i == 0)result = newnode;newnode -> nextnode = result; result = newnode;resultnum++;}}void releasemem(){int i;struct SPQ* nodefree;for ( i = 1 ; i < openednum ; i++ ) {nodefree = opened;opened = opened -> nextnode;free(nodefree);}for ( i = 0 ; i < unopenednum ; i++ ) {nodefree = unopened;unopened = unopened -> nextnode; free(nodefree);}}void showresult() /*显⽰*/{int i;int fsr , fpr ; /* 在右岸上的⼈数*/ int fsl , fpl ; /* 在左岸上的⼈数*/ struct SPQ* nodefree;printf("%d个牧师",result -> pr); printf("%d个野⼈",result -> sr); printf("%d个牧师",result -> pl); printf("%d个野⼈",result -> sl); for ( i = 1 ; i < resultnum ; i++ ) {nodefree = result;result = result -> nextnode;free(nodefree);printf("\n\n\t左岸⼈数船上⼈数及⽅向右岸⼈数\n");printf("第%d轮\n",i);fpl = result -> pl - result -> spt + result -> spr;fpr = result -> pr - result -> spr;fsl = result -> sl - result -> sst + result -> ssr;fsr = result -> sr - result -> ssr;printf("牧师%8d%8d\t<-\t%8d\n",fpl,result -> spt,fpr);printf("野⼈%8d%8d\t<-\t%8d\n",fsl,result -> sst,fsr);printf("牧师%8d%8d\t->\t%8d\n",result -> pl,result -> spr,result -> pr - result -> spr); printf("野⼈%8d%8d\t->\t%8d\n",result -> sl,result -> ssr,result -> sr - result -> ssr); }printf("\n全体牧师和野⼈全部到达对岸");free(result);}void goon() /*循环操作选择*/{char choice;for(;;){printf("\n是否继续?(Y/N)\n");scanf ("%s" , &choice);choice=toupper(choice);if(choice=='Y')break;if(choice=='N')exit(0);}}int main(){int flag; /* 标记扩展是否成功*/for( ; ; ){initiate();flag = search ();if(flag == 1){recorder();releasemem();showresult();goon();}else{printf("⽆法找到符合条件的解");releasemem();goon();}}system("pause");return 0;}void initiate(){int x;char choice;uend = unopened = (struct SPQ*)malloc(sizeof(spq));if(uend==NULL){printf("\n内存不够!\n");exit(0);}unopenednum=1;openednum=0;unopened -> upnode = unopened; /* 保存⽗结点的地址以成链表*/ unopened -> nextnode = unopened; unopened -> sr = slavenum;unopened -> pr = pristnum;unopened -> sl = 0;unopened -> pl = 0;unopened -> sst = 0;unopened -> spt = 0;unopened -> ssr = 0;unopened -> spr = 0;unopened -> loop = 0;printf("\n请输⼊牧师⼈数");for(;;){scanf("%d",&x);if(x>0){unopened -> pr = x;break;}else printf("\n输⼊值应⼤于0!\n请重新输⼊");}printf("\n请输⼊野⼈⼈数");for(;;){scanf("%d",&x);if(x>0){unopened -> sr = x;break;}else printf("\n输⼊值应⼤于0!\n请重新输⼊");}}int search(){int flag;struct SPQ *ntx; /* 提供将要扩展的结点的指针*/for( ;; ){ntx = unopened; /* 从待扩展链表中提取最前⾯的⼀个*/if(ntx->loop == maxloop)return 0;addtoopened(ntx); /* 将ntx加⼊已扩展链表,并将这个节点从待扩展链表中去掉*/ flag = stretch(ntx); /* 对ntx进⾏扩展,返回-1,0,1 */if(flag == 1)return 1;}}int stretch(struct SPQ *ntx){int fsr , fpr ; /* 在右岸上的⼈数*/int fsl , fpl ; /* 在左岸上的⼈数*/int sst , spt ; /* 出发时在船上的⼈数*/int ssr , spr ; /* 返回时船上的⼈数*/struct SPQ *newnode;for (sst = 0 ; sst <= 2 ; sst++) /* 讨论不同的可能性并判断是否符合条件*/ { fsr = ntx -> sr;fpr = ntx -> pr;fsl = ntx -> sl;fpl = ntx -> pl;if ((sst <= fsr) && (( 2 - sst) <= fpr))/* 满⾜⼈数限制*/{spt = 2 - sst;fsr = fsr - sst;fpr = fpr - spt;if((fpr == 0) && (fsr == 0))/* 搜索成功*/{newnode = (struct SPQ*) malloc (sizeof(spq));if(newnode==NULL){printf("\n内存不够!\n");exit(0);}newnode -> upnode = ntx; /* 保存⽗结点的地址以成链表*/newnode -> nextnode = NULL;newnode -> sr = 0;newnode -> pr = 0;newnode -> sl = opened -> sr;newnode -> pl = opened -> pr;newnode -> spr = 0;newnode -> loop = ntx -> loop + 1;oend -> nextnode = newnode;oend = newnode;openednum++;return 1;}else if ((fpr - fsr) * fpr >= 0) /* 判断是否满⾜传教⼠⼈数必须⼤于或等于野⼈⼈数*/ {fsl = fsl + sst;fpl = fpl + spt;for (ssr = 0 ; ssr <= 1 ; ssr++) /* 返回*/{int ffsl , ffpl;if ((ssr <= fsl) && ((1 - ssr) <= fpl)){spr = 1 - ssr;ffsl = fsl - ssr;ffpl = fpl - spr;if ((ffpl - ffsl) * ffpl >= 0){ /* 若符合条件则分配内存并付值*/int ffsr , ffpr;ffsr = fsr + ssr;ffpr = fpr + spr;newnode = (struct SPQ*) malloc (sizeof(spq));if(newnode==NULL){printf("\n内存不够!\n");exit(0);}newnode -> upnode = ntx; /* 保存⽗结点的地址以成链表*/ newnode -> sr = ffsr; newnode -> pr = ffpr;newnode -> spt = spt;newnode -> ssr = ssr;newnode -> spr = spr;newnode -> loop = ntx -> loop + 1;uend -> nextnode = newnode;uend = newnode;unopenednum++;}}}}}}return 0;}4.程序调试(实验数据记录——根据程序要求输⼊⼏组不同数据,记录程序运⾏结果,并分析结果,分析程序运⾏中出现的主要错误。
牧师与野人课程设计
数据结构课程设计报告设计题目: 牧师和野人问题院系:经济管理学院专业班级:电子商务2010-2学生姓名:孙印民、王倩、续琳琳指导教师:周长红2012年7月6日指导教师评语指导教师:年月日成绩评定学号姓名任务分工成绩1001060423 孙印民概要、详细设计、调试分析、测试结果1001060429 王倩设计内容、总结、排版1001060433 续琳需求分析、设计成果展示、总结、排版目录1.设计内容1.11.4研究思路有N1个牧师和N2个野人来到河边准备渡河,河岸有一条船,每次至多可供M人乘渡。
问牧师为了安全起见,应如何规划摆渡方案,使得任何时刻,在河的两岸以及船上的野人数目总是不超过牧师的数目。
即求解牧师和野人从左岸全部摆渡到右岸的过程中,任何时刻满足N1(牧师数)≥N2(野人数)和N1+N2≤M的摆渡方案。
首先从比较简单的入手,先设N1=N2=3,M=2,则给定的问题可用图1.2表示,图中L和R表示左岸和右岸,B=1或0分别表示有船或无船。
约束条件是:两岸上N1≥N2,船上N1+N2≤2。
图1.2 N1-N2问题实例由于牧师和野人数是一个常数,所以知道了一岸的情况,另一岸的情况也就知道了。
因此为了简便起见,在描述问题时,只描述一岸(如左岸)的情况就可以了。
另外,该问题我们最关心的是在摆渡过程中,两岸状态的变化情况,因此船上的情况并不需要直接表达出来。
在一次摆渡过程中,船上究竟有几个牧师和野人,可以通过两个相连的状态简单得到。
这样表达更简练,突出了问题的重点。
(1)综合数据库:用三元组表示左岸的情况,即(N1,N2,B),其中0≤N1,N2≤3,B∈{0,1},其中N1表示在左岸的牧师人数,N2表示在左岸的野人数,B=1表示船在左岸,B=0表示船在右岸。
则此时问题描述可以简化为:(3,3,1)→(0,0,0)N=3的N1-N2问题,状态空间的总状态数为4×4×2=32,根据约束条件的要求,可以看出只有20个合法状态。
野人过河问题算法分析
野人过河问题算法分析野人过河问题属于人工智能学科中的一个经典问题,问题描述如下:有三个牧师(也有的翻译为传教士)和三个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于牧师的人数,那么牧师就会有危险. 你能不能找出一种安全的渡河方法呢?一、算法分析先来看看问题的初始状态和目标状态,假设和分为甲岸和乙岸:初始状态:甲岸,3野人,3牧师;乙岸,0野人,0牧师;船停在甲岸,船上有0个人;目标状态:甲岸,0野人,0牧师;乙岸,3野人,3牧师;船停在乙岸,船上有0个人;整个问题就抽象成了怎样从初始状态经中间的一系列状态达到目标状态。
问题状态的改变是通过划船渡河来引发的,所以合理的渡河操作就成了通常所说的算符,根据题目要求,可以得出以下5个算符(按照渡船方向的不同,也可以理解为10个算符):渡1野人、渡1牧师、渡1野人1牧师、渡2野人、渡2牧师算符知道以后,剩下的核心问题就是搜索方法了,本文采用深度优先搜索,通过一个FindNext(…)函数找出下一步可以进行的渡河操作中的最优操作,如果没有找到则返回其父节点,看看是否有其它兄弟节点可以扩展,然后用Process(…)函数递规调用FindNext(…),一级一级的向后扩展。
搜索中采用的一些规则如下:1、渡船优先规则:甲岸一次运走的人越多越好(即甲岸运多人优先),同时野人优先运走;乙岸一次运走的人越少越好(即乙岸运少人优先),同时牧师优先运走;2、不能重复上次渡船操作(通过链表中前一操作比较),避免进入死循环;3、任何时候河两边的野人和牧师数均分别大于等于0且小于等于3;4、由于只是找出最优解,所以当找到某一算符(当前最优先的)满足操作条件后,不再搜索其兄弟节点,而是直接载入链表。
5、若扩展某节点a的时候,没有找到合适的子节点,则从链表中返回节点a的父节点b,从上次已经选择了的算符之后的算符中找最优先的算符继续扩展b。
二、基本数据结构仔细阅读问题,可以发现有些基本东西我们必须把握,例如:每时刻河两岸野人牧师各自的数目、船的状态、整个问题状态。
职高数学教学案例1
职高数学教学案例有一个牧羊人带着一头羊,一只狼和一颗大白菜准备过河,他找到一只很小的船,每次只能带一样东西过去,可是如果让狼与羊单独在一起,狼会吃羊,让羊与白菜单独在一起,羊会吃白菜,牧羊人应如何过河?同学们一齐回答:这太简单了。
马上给出过河方案:第一步:人和羊过河,人返回,留下羊;第二步:人和狼过河,人和羊返回,留下狼;第三步:人和菜过河,人返回,留下菜;第四步:人和羊过河。
教师看到后说:你们太有才了,请看《过河》第二版,野人过河有三个牧师和三个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于牧师的人数,那么牧师就会有危险。
你能不能找出一种安全的渡河方法呢?给出游戏:学生上机实验让先成功的学生上机演示并解释说明①两个野人先过河,一个野人回来;②再两个野人过河,一个野人回来;③两个牧师过河,一个野人和一个牧师回来;④两个牧师过河,一个野人回来;⑤两个野人过河,一个野人回来;⑥两个野人过河。
设计意图:活跃课堂气氛,在游戏中积极思考,寻求解决问题方法。
教师总结出算法的概念:这个过河的方案就是这道趣味题的算法。
请同学们记住一句话:算法就是解决问题的方法和步骤。
案例分析:让同学们看书p10,p11页鸡兔同笼的案例,如何是用自然语言和流程图表示的。
留出充足的时间让小组讨论如何写算法,自然语言和流程图各自具备什么特点,让学生初步形成算法思想。
算法的择优(1)(教师)处理同一个问题可能有不同的算法,采用什么样的算法更简单、方便呢?(2)放幻灯片,出示例子:著名数学家华罗庚“烧水泡茶”的两个算法。
算法一第一步:烧水;第二步:水烧开后,洗刷茶具;第三步:沏茶。
算法二第一步:烧水;第二步:烧水过程中,洗刷茶具;第三步:水烧开后沏茶。
(3)(教师)大家讲讨论一下两者有何不同?哪个算法效率高一些?(4)(学生)区别是在什么时间洗刷茶具。
第二个算法更高效,因为节约时间。
(5)(教师)很好。
算法来源于生活,算法的设计,直接影响着解决问题的效率,总的来说,一个好的算法,应该是科学而又合理的算法。
过河问题的解题思路
过河问题的解题思路一、问题描述过河问题是一个经典的数学问题,也是一个有趣的思维游戏。
问题描述如下:有一只船,它每次能载两个人过河,但是在河的两岸只有一个灯泡,而且这个灯泡的光线很暗,只能照亮一个人。
在黑暗中无法看到对岸,你只知道在河的这一侧有A、B、C、D四个人,分别需要2、5、10、20分钟才能过河。
过河的过程中,灯泡必须始终在人的附近,否则将无法过河。
求最短时间内将所有人都安全过河的方案。
二、问题分析过河问题涉及到多个因素:船只的容纳能力、灯泡的照明范围、人员的移动速度等。
为了找到最短时间内的安全过河方案,我们需要综合考虑这些因素,并进行合理的规划。
三、解题思路为了找到最短时间内的过河方案,我们可以采取以下步骤:1. 确定过河策略为了尽可能减少过河的总时间,我们应该尽量将速度较快的人员优先过河,以确保船只能够尽快返回。
另外,由于灯泡的范围有限,我们需要灵活安排人员的过河顺序,避免出现照不到灯泡的情况。
2. 划分人员的移动区域考虑到灯泡的照明范围有限,我们可以将河的一侧划分为两个区域:A区和B区。
初始时,所有人都在A区,船只位于A区。
为了尽量减少船只的往返次数,我们可以将速度快的人员先安排到B区等待过河。
3. 制定过河方案根据人员的移动速度,我们可以制定如下的过河方案:•A区的人员按照速度从小到大的顺序过河,快的人员优先过河,慢的人员后过河。
•B区的人员限制数量为2人。
如果B区有两个人等待过河,船只运送他们过河,船只返回A区,将其中一个速度最快的人员带到B区。
•B区的人员按照速度从小到大的顺序过河,快的人员优先过河,慢的人员后过河。
重复以上步骤,直到所有人员都安全到达河的对岸。
四、过河示意图为了更好地理解过河方案,以下是过河的示意图:初始状态:A区(ABCD)———————河————————B区()1.第一次过河:船只带着速度最快的两个人(A和B)从A区到B区状态:A区(CD)———————河————————B区(AB)2.第二次过河:船只带着速度最快的人(A)从B区返回A区,然后带着速度最慢的两个人(C和D)从A 区到B区状态:A区()———————河————————B区(ABCD)3.第三次过河:船只带着速度最快的两个人(A和B)从B区返回A区状态:A区(ABCD)———————河————————B区()4.第四次过河:船只带着速度第二快的人(B)从A区到B区状态:A区(ACD)———————河————————B区(B)5.第五次过河:船只带着速度最快的人(A)从B区返回A区,然后带着速度最慢的两个人(C和D)从A 区到B区状态:A区()———————河————————B区(ABCD)6.第六次过河:船只带着速度最快的两个人(A和B)从B区返回A区状态:A区(ABCD)———————河————————B区()五、最短时间根据以上过河方案,可以计算出最短时间为:2 + 2 + 1 + 10 + 5 + 2 = 22分钟六、总结通过合理的过河策略和灵活的分区安排,我们可以找到最短时间内的过河方案。
传教士野人过河问题-两种解法思路
实验 传教士野人过河问题37030602 王世婷一、实验问题传教士和食人者问题(The Missionaries and Cannibals Problem )。
在河的左岸有3个传教士、1条船和3个食人者,传教士们想用这条船将所有的成员运过河去,但是受到以下条件的限制:(1)传教士和食人者都会划船,但船一次最多只能装运两个;(2)在任何岸边食人者数目都不得超过传教士,否则传教士就会遭遇危险:被食人者攻击甚至被吃掉。
此外,假定食人者会服从任何一种过河安排,试规划出一个确保全部成员安全过河的计划。
二、解答步骤(1) 设置状态变量并确定值域M 为传教士人数,C 为野人人数,B 为船数,要求M>=C 且M+C <= 3,L 表示左岸,R 表示右岸。
初始状态 目标状态L R L RM 3 0 M 0 3C 3 0 C 0 3B 1 0 B 0 1(2) 确定状态组,分别列出初始状态集和目标状态集用三元组来表示f S :(ML , CL , BL )(均为左岸状态)其中03,03ML CL ≤≤≤≤,BL ∈{ 0 , 1}0S :(3 , 3 , 1) g S : (0 , 0 , 0)初始状态表示全部成员在河的的左岸;目标状态表示全部成员从河的左岸全部渡河完毕。
(3) 定义并确定规则集合仍然以河的左岸为基点来考虑,把船从左岸划向右岸定义为Pij 操作。
其中,第一下标i 表示船载的传教士数,第二下标j 表示船载的食人者数;同理,从右岸将船划回左岸称之为Qij 操作,下标的定义同前。
则共有10种操作,操作集为F={P01,P10,P11,P02,P20,Q01,Q10,Q11,Q02,Q20}P 10 if ( ML ,CL , BL=1 ) then ( ML –1 , CL , BL –1 )P 01 if ( ML ,CL , BL=1 ) then ( ML , CL –1 , BL –1 )P 11 if ( ML ,CL , BL=1 ) then ( ML –1 , CL –1 , BL –1 )P 20 if ( ML ,CL , BL=1 ) then ( ML –2 , CL , BL –1 )P 02 if ( ML ,CL , BL=1 ) then ( ML , CL –2 , BL –1 )Q 10 if ( ML ,CL , BL=0 ) then ( ML+1 , CL , BL+1 )Q 01 if ( ML ,CL , BL=0 ) then ( ML , CL+1 , BL +1 )Q 11 if ( 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 )(4)当状态数量不是很大时,画出合理的状态空间图图1 状态空间图箭头旁边所标的数字表示了P或Q操作的下标,即分别表示船载的传教士数和食人者数。
人工智能+野人传教士过河问题c程序+深度优先
open[top].m=M;
open[top].c=C;
open[top].s=S;
open[top].f=0;
open[top].pre=0;
inist();
find(pHead);
system("PAUSE");
{
flag=0;
break;
}
pTemp=pTemp->pre;
}
if(flag)
{
j++;
boatState[j].m = m;
boatState[j].c = c;
}
}
}
}
//*******************************************************************************
int goal(struct state * p) //判断当前状态是否目标状态
{
if(p->m==0&&p->c==0&&p->s==1) return 1;
else return 0;
}
//******************************************************************************
//初始状态:左岸,3野人,3牧师;
// 右岸,0野人,0牧师;
// 船停在左岸,船上有0个人
//目标状态:左岸,0野人,0牧师;
// 右岸,3野人,3牧师;
// 船停在右岸,船上有0个人;
多维棋最经典的推理游戏——牧师过河,你会玩吗?
多维棋最经典的推理游戏——牧师过河,你会玩吗?展开全文(多维棋专栏)多维棋既是一套通过“操作”开发儿童潜能的教学方法,又是一系列从平面到立体不同层次、多维度的棋类思维游戏。
多维棋有别于传统的象棋和围棋,棋盘、棋子、棋规都是可以变化的。
棋盘是根据各类对弈的需要而制作的,不同的棋盘应用不同的棋子,亦可根据教学的需要制定不同的棋规。
多维棋教学不是把对弈的结果放在第一位,而是注重教学的过程,以在行棋过程中提升儿童的各种能力为核心思想,最终达到开发儿童潜能,增智益慧的目的。
多维棋的训练主旨是对儿童思维水平的提高训练,使其形成独特的“棋思维”模式,打破传统棋类的娱乐主旨。
学一棋得到一个好思维的方法,重视“最佳方案”的选择,形成智慧思维。
行棋的过程,就是从众多方案中选取最佳方案形成最佳的思维模式。
本期小编介绍的这个“牧师过河”游戏,是多维棋课程中一个非常经典的逻辑推理游戏,是一个单人益智游戏。
各位家长不妨带着孩子开动一下脑筋玩一玩。
游戏故事背景:相传很久以前,有3个牧师在传道的途中,遇到一条河,河很宽,河上也没有船,虽然都会划船,可他们却不会游泳,正在着急的时候,突然从树林里串出3个食人族的野人,直奔他们跑来。
这3个牧师就开始了奋力反抗,结果和3个野人打了个平手,野人的“领头”就对牧师说:“你们不是过河吗,我们其实也要过河,正好我们有一条可以坐两人的小船,可以载你们过去。
我们一起过吧!”3个牧师一听,就知道黄鼠狼给鸡拜年。
果然野人又说:“不过,当船上或岸上你们的人数少于我们的人数时,我们可就不客气了。
”牧师们一听都害怕,可有一个聪明的牧师想了想就答应了野人的要求,结果他们都安全地过河了。
大家知不知道牧师是怎么过河的呢?我们把这个故事的情景用多维棋来演绎出来,看看聪明的你几步能把所有的牧师都安全地运过河去。
棋盘上的两条线之间就代表那条河,白色棋子代表牧师,黑色棋子代表野人。
对岸的智慧棒代表他们想要到的地方。
从故事中我们提取有用的信息:1、白珠代表牧师,黑珠代表野人。
野人和传教士过河问题的C语言源代码
野⼈和传教⼠过河问题的C语⾔源代码 1//问题:有3个传教⼠和3个野⼈要过河,只有⼀艘船,这艘船每次2//只能载2个⼈过河,且⽆论哪边野⼈的数量⼤于传教⼠的数量时,3//野⼈就会吃掉传教⼠。
怎样让他们都安全过河?45 #include <stdio.h>6 #include <string.h>78#define STEP_MAX 20 //来回过河的次数9#define KIND_NUM 3 //每个种类的数量10#define BOAT_NUM 2 //船的载重量1112 typedef enum13 {14 BOAT_THIS,//船在本岸15 BOAT_THAT,//船在对岸16 } boat_t;1718 typedef enum19 {20 ROAD_GO,//过河21 ROAD_COME,//回来22 } road_t;2324 typedef struct25 {26int ye;//对岸野⼈数量27int man;//对岸传教⼠数量28 boat_t boat;//船是否在对岸29 } state_t;//⼀种局⾯3031 typedef struct32 {33int ye;//野⼈过河数量34int man;//传教⼠过河的数量35 road_t road;//回来或过河36 } step_t;//⼀个步骤373839 state_t states[STEP_MAX] = { 0 };40 step_t steps[STEP_MAX] = { 0 };414243//判断所有的野⼈和传教⼠是否都到了对岸44bool final(state_t s)45 {46const state_t cs =47 {48 KIND_NUM,49 KIND_NUM,50 BOAT_THAT51 };52if (memcmp(&cs, &s, sizeof(state_t)) == 0)53 {54return true;55 }56return false;57 }5859//是否会发⽣野⼈杀传教⼠60bool bad(state_t s)61 {62if (((KIND_NUM - s.ye) > (KIND_NUM - s.man)63 && (KIND_NUM - s.man) > 0)64 || (s.ye > s.man&& s.man > 0))65 {66return true;67 }68return false;69 }7071//第n种局⾯是否跟前⾯的相重复72bool repeat(state_t s[], int n)73 {74int i;7576for (i = 0; i < n; i++)77 {//已经有这种情况了78if (memcmp(&states[i], &states[n], sizeof(states[i])) == 0)79 {80return true;81 }82 }83return false;84 }8586void output(step_t steps[STEP_MAX], int n)87 {88const char* kinds[KIND_NUM] = { "野⼈","传教⼠" };89const char* roads[2] = { "过河.","回来." };90int i;9192for (i = 0; i < n; i++)93 {94if ((steps[i].ye * steps[i].man) > 0)95 {96 printf("%d个%s和%d个%s%s\n", steps[i].ye, kinds[0],97 steps[i].man, kinds[1], roads[steps[i].road]);98 }99else if (steps[i].ye > 0)100 {101 printf("%d个%s%s\n", steps[i].ye, kinds[0],102 roads[steps[i].road]);103 }104else if (steps[i].man > 0)105 {106 printf("%d个%s%s\n", steps[i].man, kinds[1],107 roads[steps[i].road]);108 }109 }110 printf("\n");111 }112113//搜索过河⽅案(n表⽰过河次数)114void search(int n)115 {116int i, j;117118if (n > STEP_MAX)119 {//步数限制太少了120 printf("Step Overflow!");121return;122 }123if (final(states[n]))124 {//都到对岸了125 output(steps, n);126return;127 }128if (bad(states[n]))129 {//发⽣了野⼈杀传教⼠了130return;131 }132if (repeat(states, n))133 {//与前⾯的局⾯相重复了134return;135 }136if (states[n].boat == BOAT_THIS)137 {//船在本岸138for (i = 0; i <= BOAT_NUM && i <= (KIND_NUM - states[n].ye); i++)139for (j = 0; j <= BOAT_NUM - i && j <= (KIND_NUM - states[n].man); j++) 140 {141if (i == 0 && j == 0)142 {143continue;144 }145 steps[n].ye = i;146 steps[n].man = j;147 steps[n].road = ROAD_GO;148 memcpy(&states[n + 1], &states[n], sizeof(state_t));149 states[n + 1].ye += i;150 states[n + 1].man += j;151 states[n + 1].boat = BOAT_THAT;152 search(n + 1);153 }154 }155else156 {157for (i = 0; i <= BOAT_NUM && i <= states[n].ye; i++)158 {159for (j = 0; j <= BOAT_NUM - i && j <= states[n].man; j++)160 {161if (i == 0 && j == 0)162 {163continue;164 }165 steps[n].ye = i;166 steps[n].man = j;167 steps[n].road = ROAD_COME;168 memcpy(&states[n + 1], &states[n], sizeof(state_t)); 169 states[n + 1].ye -= i;170 states[n + 1].man -= j;171 states[n + 1].boat = BOAT_THIS;172 search(n + 1);173 }174 }175 }176 }177178int main()179 {180 search(0);181return0;182 }1个野⼈和1个传教⼠过河.1个传教⼠回来.2个野⼈过河.1个野⼈回来.2个传教⼠过河.1个野⼈和1个传教⼠回来.2个传教⼠过河.1个野⼈回来.2个野⼈过河.1个传教⼠回来.1个野⼈和1个传教⼠过河.1个野⼈和1个传教⼠过河.1个传教⼠回来.2个野⼈过河.1个野⼈回来.2个传教⼠过河.1个野⼈和1个传教⼠回来.2个传教⼠过河.1个野⼈回来.2个野⼈过河.1个野⼈回来.2个野⼈过河.2个野⼈过河.1个野⼈回来.2个野⼈过河.1个野⼈回来.2个传教⼠过河.1个野⼈和1个传教⼠回来.2个传教⼠过河.1个野⼈回来.2个野⼈过河.1个传教⼠回来.1个野⼈和1个传教⼠过河.2个野⼈过河.1个野⼈回来.2个野⼈过河.1个野⼈回来.2个传教⼠过河.1个野⼈和1个传教⼠回来.2个传教⼠过河.1个野⼈回来.2个野⼈过河.1个野⼈回来.2个野⼈过河.。
逻辑思维能力测试题
选择题:1、选出不同类的一项:A、蛇B、大树C、老虎2、在下列分数中,选出不同类的一项:A 3/5 B 3/7 C 3/93、男孩对男子,正如女孩对A青年B孩子C夫人D姑娘E妇女4、如果笔相对于写字,那么书相对于A娱乐B阅读C学文化D解除疲劳5、马之于马厩,正如人之于A牛棚B马车C房屋D农场E楼房6、2 8 14 20 ()请写出“ ()”处的数字。
7、下列四个词是否可以组成一个正确的句子生活水里鱼在 A 是B否8、下列六个词是否可以组成一个正确的句子球棒的用来是棒球打A是B否9、动物学家与社会学家相对应,正如动物与()相对A人类B问题C社会D社会学10、如果所有的妇女都有大衣,那么漂亮的妇女会有A更多的大衣B时髦的大衣C 大衣D昂贵的大衣11、1 3 2 4 6 5 7 (),请写出“ ()”处的数字12、南之于西北,正如西之于:A西北B东北C西南D东南13、找出不同类的一项A铁锅B小勺C米饭D碟子14、9 7 8 6 7 5 (),请写出“ ()”处的数字15、找出不同类的一项:A写字台B沙发C电视D桌布16、961 (25)432 932 ()731 ,请写出()内的数字17、选项ABCD中,哪一个应该填在“XOOOOXXOOOXXX”后面AXOO BOO COOX DOXX18、望子成龙的家长往往()苗助长A揠B堰C偃19、填上空缺的词:金黄的头发(黄山)刀山火海赞美人生()卫国战争20、选出不同类的一项:A地板B壁橱C窗户D窗帘21、1 8 27 (),请写出()内的数字。
22、填上空缺的词:罄竹难书(书法)无法无天作奸犯科()教学相长23、在括号内填上一个字,使其与括号前的字组成一个词,同时又与括号后的字也能组成一个词:款()样24、填入空缺的数字:16(96)12 10()7.525找出不同类的一项:A斑马B军马C赛马D骏马E驸马26、在括号上填上一个字,使其与括号前的字组成一个词,同时又与括号后的字也能组成一个词:祭()定27、在括号内填上一个字,使之既有前一个词的意思,又可以与后一个词组成词组:头部()震荡28、填入空缺的数字65 37 17 ()29、填入空缺的数字41(28)27 83()6530、填上空缺的字母CFI DHL EJ()参考答案:1、B;2、C;3、E;4、B;5、C;6、26;7、A;8、B;9、A;10、C;11、9;12、B;13、C;14、6;15、D;16、38;17、B;18、A;19、美国;20、D;21、58;22、科学;23、式;24、60;25、E;26、奠;27、脑;28、5;29、36;30、O.判断题:1大象是动物,动物有腿。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
人工智能上机实验报告学号:姓名:所在系:信息学院班级:实验名称:实验日期2016年12月3日实验指导教师实验机房A401------------------------------------------------------------------------------------------------------ 1.实验目的:(1)在掌握状态空间搜索策略的基础上,理解知识表示的方法。
(2)能够应用知识表示方法,解决实际问题2. 实验内容:(1)M-C问题描述有n个牧师和n个野人准备渡河,但只有一条能容纳c个人的小船,为了防止野人侵犯牧师,要求无论在何处,牧师的人数不得少于野人的人数(除非牧师人数为0),且假定野人与牧师都会划船,试设计一个算法,确定他们能否渡过河去,若能,则给出小船来回次数最少的最佳方案。
3.算法设计(编程思路或流程图或源代码)#include <stdio.h>#include <stdlib.h>#include <ctype.h>#define maxloop 100 /* 最大层数,对于不同的扩展方法自动调整取值*/#define pristnum 3 /*初始化时设定有3个野人3个牧师,实际可以改动*/#define slavenum 3struct SPQ{ int sr,pr; /* 船运行一个来回后河右岸的野人、牧师的人数*/int sl,pl; /* 船运行一个来回后河左岸的野人、牧师的人数*/int ssr,spr; /* 回来(由左向右时)船上的人数*/int sst,spt; /* 去时(由右向左时)船上的人数*/int loop; /* 本结点所在的层数*/struct SPQ *upnode ,*nextnode;/* 本结点的父结点和同层的下一个结点的地址*/}spq;int loopnum;/* 记录总的扩展次数*/int openednum;/* 记录已扩展节点个数*/int unopenednum;/* 记录待扩展节点个数*/int resultnum;struct SPQ *opened;struct SPQ *oend;struct SPQ *unopened;struct SPQ *uend;struct SPQ *result;void initiate();void releasemem();void showresult();void addtoopened(struct SPQ *ntx);int search();void goon();int stretch(struct SPQ* ntx);void recorder();void addtoopened(struct SPQ *ntx) /*扩展节点*/ {unopened = unopened -> nextnode; unopenednum--;if (openednum == 0 )oend = opened = ntx;oend -> nextnode = ntx;oend = ntx;openednum++;}void recorder(){int i , loop;struct SPQ *newnode;struct SPQ *ntx;loop = oend -> loop;ntx = oend;resultnum = 0;for( i = 0 ; i <= loop ; i++ ){newnode = (struct SPQ*) malloc (sizeof(spq));if(newnode==NULL){printf("\n内存不够!\n");exit(0);}newnode -> sr = ntx -> sr;newnode -> pr = ntx -> pr;newnode -> sl = ntx -> sl;newnode -> pl = ntx -> pl;newnode -> sst = ntx -> sst;newnode -> spt = ntx -> spt; newnode -> ssr = ntx -> ssr; newnode -> spr = ntx -> spr; newnode -> nextnode = NULL;ntx = ntx -> upnode;if(i == 0)result = newnode;newnode -> nextnode = result; result = newnode;resultnum++;}}void releasemem(){int i;struct SPQ* nodefree;for ( i = 1 ; i < openednum ; i++ ) {nodefree = opened;opened = opened -> nextnode;free(nodefree);}for ( i = 0 ; i < unopenednum ; i++ ) {nodefree = unopened;unopened = unopened -> nextnode; free(nodefree);}}void showresult() /*显示*/{int i;int fsr , fpr ; /* 在右岸上的人数*/ int fsl , fpl ; /* 在左岸上的人数*/ struct SPQ* nodefree;printf("%d个牧师",result -> pr); printf("%d个野人",result -> sr); printf("%d个牧师",result -> pl); printf("%d个野人",result -> sl); for ( i = 1 ; i < resultnum ; i++ ) {nodefree = result;result = result -> nextnode;free(nodefree);printf("\n\n\t左岸人数船上人数及方向右岸人数\n");printf("第%d轮\n",i);fpl = result -> pl - result -> spt + result -> spr;fpr = result -> pr - result -> spr;fsl = result -> sl - result -> sst + result -> ssr;fsr = result -> sr - result -> ssr;printf("牧师%8d%8d\t<-\t%8d\n",fpl,result -> spt,fpr);printf("野人%8d%8d\t<-\t%8d\n",fsl,result -> sst,fsr);printf("牧师%8d%8d\t->\t%8d\n",result -> pl,result -> spr,result -> pr - result -> spr);printf("野人%8d%8d\t->\t%8d\n",result -> sl,result -> ssr,result -> sr - result -> ssr);}printf("\n全体牧师和野人全部到达对岸");free(result);}void goon() /*循环操作选择*/{char choice;for(;;){printf("\n是否继续?(Y/N)\n");scanf ("%s" , &choice);choice=toupper(choice);if(choice=='Y')break;if(choice=='N')exit(0);}}int main(){int flag; /* 标记扩展是否成功*/for( ; ; ){initiate();flag = search ();if(flag == 1){recorder();releasemem();showresult();goon();}else{printf("无法找到符合条件的解");releasemem();goon();}}system("pause");return 0;}void initiate(){int x;char choice;uend = unopened = (struct SPQ*)malloc(sizeof(spq));if(uend==NULL){printf("\n内存不够!\n");exit(0);}unopenednum=1;openednum=0;unopened -> upnode = unopened; /* 保存父结点的地址以成链表*/ unopened -> nextnode = unopened;unopened -> sr = slavenum;unopened -> pr = pristnum;unopened -> sl = 0;unopened -> pl = 0;unopened -> sst = 0;unopened -> spt = 0;unopened -> ssr = 0;unopened -> spr = 0;unopened -> loop = 0;printf("\n请输入牧师人数");for(;;){scanf("%d",&x);if(x>0){unopened -> pr = x;break;}else printf("\n输入值应大于0!\n请重新输入");}printf("\n请输入野人人数");for(;;){scanf("%d",&x);if(x>0){unopened -> sr = x;break;}else printf("\n输入值应大于0!\n请重新输入");}}int search(){int flag;struct SPQ *ntx; /* 提供将要扩展的结点的指针*/for( ;; ){ntx = unopened; /* 从待扩展链表中提取最前面的一个*/if(ntx->loop == maxloop)return 0;addtoopened(ntx); /* 将ntx加入已扩展链表,并将这个节点从待扩展链表中去掉*/flag = stretch(ntx); /* 对ntx进行扩展,返回-1,0,1 */if(flag == 1)return 1;}}int stretch(struct SPQ *ntx){int fsr , fpr ; /* 在右岸上的人数*/int fsl , fpl ; /* 在左岸上的人数*/int sst , spt ; /* 出发时在船上的人数*/int ssr , spr ; /* 返回时船上的人数*/struct SPQ *newnode;for (sst = 0 ; sst <= 2 ; sst++) /* 讨论不同的可能性并判断是否符合条件*/ {fsr = ntx -> sr;fpr = ntx -> pr;fsl = ntx -> sl;fpl = ntx -> pl;if ((sst <= fsr) && (( 2 - sst) <= fpr))/* 满足人数限制*/{spt = 2 - sst;fsr = fsr - sst;fpr = fpr - spt;if((fpr == 0) && (fsr == 0))/* 搜索成功*/{newnode = (struct SPQ*) malloc (sizeof(spq));if(newnode==NULL){printf("\n内存不够!\n");exit(0);}newnode -> upnode = ntx; /* 保存父结点的地址以成链表*/newnode -> nextnode = NULL;newnode -> sr = 0;newnode -> pr = 0;newnode -> sl = opened -> sr;newnode -> pl = opened -> pr;newnode -> sst = sst;newnode -> spt = spt;newnode -> ssr = 0;newnode -> spr = 0;newnode -> loop = ntx -> loop + 1;oend -> nextnode = newnode;oend = newnode;openednum++;return 1;}else if ((fpr - fsr) * fpr >= 0) /* 判断是否满足传教士人数必须大于或等于野人人数*/{fsl = fsl + sst;fpl = fpl + spt;for (ssr = 0 ; ssr <= 1 ; ssr++) /* 返回*/{int ffsl , ffpl;if ((ssr <= fsl) && ((1 - ssr) <= fpl)){spr = 1 - ssr;ffsl = fsl - ssr;ffpl = fpl - spr;if ((ffpl - ffsl) * ffpl >= 0){ /* 若符合条件则分配内存并付值*/int ffsr , ffpr;ffsr = fsr + ssr;ffpr = fpr + spr;newnode = (struct SPQ*) malloc (sizeof(spq));if(newnode==NULL){printf("\n内存不够!\n");exit(0);}newnode -> upnode = ntx; /* 保存父结点的地址以成链表*/ newnode -> sr = ffsr;newnode -> pr = ffpr;newnode -> sl = ffsl;newnode -> pl = ffpl;newnode -> sst = sst;newnode -> spt = spt;newnode -> ssr = ssr;newnode -> spr = spr;newnode -> loop = ntx -> loop + 1;uend -> nextnode = newnode;uend = newnode;unopenednum++;}}}}}}return 0;}4.程序调试(实验数据记录——根据程序要求输入几组不同数据,记录程序运行结果,并分析结果,分析程序运行中出现的主要错误。