人工智能里野人和传教士问题代码
传教士和野人问题
传教士和野人问题(Missionaries and Cannibals)传教士和野人问题是一个经典的智力游戏问题。
在这个问题中,实际上隐含了这样一个条件:如果在河的某一岸只有野人,而没有传教士,也同样被认为是合法状态。
在具体书写某些条件时,为了简便,这一点有时并没有考虑,但我们默认这个条件是被考虑了的。
有N个传教士和N个野人来到河边准备渡河,河岸有一条船,每次至多可供k人乘渡。
问传教士为了安全起见,应如何规划摆渡方案,使得任何时刻,在河的两岸以及船上的野人数目总是不超过传教士的数目。
即求解传教士和野人从左岸全部摆渡到右岸的过程中,任何时刻满足M(传教士数)≥C(野人数)和M+C≤k的摆渡方案。
设N=3,k=2,则给定的问题可用图1.2表示,图中L和R表示左岸和右岸,B=1或0分别表示有船或无船。
约束条件是:两岸上M≥C,船上M+C≤2。
图1.2 M-C问题实例由于传教士和野人数是一个常数,所以知道了一岸的情况,另一岸的情况也就知道了。
因此为了简便起见,在描述问题时,只描述一岸--如左岸--的情况就可以了。
另外,该问题我们最关心的是在摆渡过程中,两岸状态的变化情况,因此船上的情况并不需要直接表达出来。
在一次摆渡过程中,船上究竟有几个传教士和野人,可以通过两个相连的状态简单得到。
这样表达更简练,突出了问题的重点。
(1)综合数据库:用三元组表示左岸的情况,即(,,),其中0≤,≤3,∈{0,1},其中表示在左岸的传教士人数,表示在左岸的野人数,=1表示船在左岸,=0表示船在右岸。
则此时问题描述可以简化为:(3,3,1)→(0,0,0)N=3的M-C问题,状态空间的总状态数为4×4×2=32,根据约束条件的要求,可以看出只有20个合法状态。
再进一步分析后,又发现有4个合法状态实际上是不可能达到的。
因此实际的问题空间仅由16个状态构成。
下表列出分析的结果:()(001)达不到(传教士均在右,船在左)(011)(021)(031)(101)不合法(右岸野人多)(111)(121)不合法(左岸野人多)(131)不合法(左岸野人多)(201)不合法(右岸野人多)(211)不合法(右岸野人多)(221)(231)不合法(左岸野人多)(301)达不到()(000)(010)(020)(030)达不到(100)不合法(右岸野人多)(110)(120)不合法(左岸野人多)(130)不合法(左岸野人多)(200)不合法(右岸野人多)(210)不合法(右岸野人多)(230)不合法(右岸野人多)(300)(220)(310)(320)(330)达不到(311)(321)(331)规则集可以划分为两组:一组是从左岸到右岸,称为p操作,另一组是从右岸到左岸,称为q操作。
《人工智能基础》名词术语
1,AI:AI是人工智能英文单词Artificial Intelligence的缩写。
2,人工智能:人工智能是研究如何制造出人造的智能机器或智能系统,来模拟人类智能活动的能力,以延伸人们智能的科学。
3,产生式系统:产生式系统是Post于1943年提出的一种计算形式体系里所使用的术语,主要是使用类似于文法的规则,对符号串作替换运算。
到了60年代产生式系统成为认知心理学研究人类心理活动中信息加工过程的基础,并用它来建立人类认识的模型。
到现在产生式系统已发展成为人工智能系统中最典型最普遍的一种结构,例如目前大多数的专家系统都采用产生式系统的结构来建造。
产生式系统由综合数据库、一组产生式规则(规则集)和一个控制系统(控制策略)三部分组成,称为产生式系统的三要素。
4,产生式系统的三要素:产生式系统的三要素是综合数据库、一组产生式规则(规则集)和一个控制系统(控制策略)。
5,产生式规则:产生式规则是知识表示的一种形式,其形式如下: IF <前件> THEN <后件> 其中规则的<前件>表达的是该条规则所要满足的条件,规则的<后件>表示的是该规则所得出的结论,或者动作。
规则表达的可以是与待求解的问题有关的客观规律方面的知识,也可以是对求解问题有帮助的策略方面的知识。
6,八数码游戏(八数码问题):八数码游戏(八数码问题)描述为:在3×3组成的九宫格棋盘上,摆有八个将牌,每一个将牌都刻有1-8八个数码中的某一个数码。
棋盘中留有一个空格,允许其周围的某一个将牌向空格移动,这样通过移动将牌就可以不断改变将牌的布局。
这种游戏求解的问题是:给定一种初始的将牌布局或结构(称初始状态)和一个目标的布局(称目标状态),问如何移动将牌,实现从初始状态到目标状态的转变。
7,传教士和野人问题(M-C问题):传教士和野人问题描述为:有N个传教士和N个野人来到河边准备渡河,河岸有一条船,每次至多可供k人乘渡。
传教士(牧师)与野人问题-模拟人工智能实验_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);实验结果展示。
野人与传教士问题A算法
野人与传教士问题(A*算法)SY0903620 赵磊一、实验题目请用A*算法实现传教士和野人问题问题:设有3个传教士和3个野人来到河边,打算乘一只船从右岸渡到左岸去。
该船的负载能力为两人。
在任何时候,如果野人人数超过传教士人数,那么野人就会把传教士吃掉。
他们怎样才能用这条船安全地把所有人都渡过河去?算法设计要求给出:状态表示,规则库,启发函数等二、实验目的通过具体问题的编程求解,利用A*算法解决此经典问题,了解人工智能的启发式搜索算法的基本过程与原理。
三、设计思想1、编程工具采用C++语言在Visual Studio 6.0环境下编写;2、整体思想(1)把初始结点So放入OPEN 表中,计算f(So)。
(2)如果OPEN为空,则搜索失败,退出。
(3)把OPEN中的第一个节点(记为节点n)从表中移出放入CLOSED表。
(4)考察节点n是否为目标节点。
若是,则求得问题的解,退出。
(5)若节点n不可扩展,则转第(2)步。
(6)扩展节点n,用估价函数f(x)计算每个子节点的估价值,并为每个子节点配置指向父节点的指针,把这些子节点都送到OPEN表中,然后对OPEN表中的全部节点按估价值从小到大的顺序排列。
3、具体说明用A*算法求解传教士与野人问题。
M=C=5, K=3。
节点估价值设为f(n)=h(n)+g(n),g(n)设为节点搜索深度,而h(n)= m(n) + c(n) - 2b(n),其中m:河左岸的传教士人数;c:河左岸的野人人数;b:船是否在左岸,1:表示在左岸,0:表示不在左岸。
采用结构体定义形式,定义状态节点*NewNode(int m, int c, int b),其中包含m左岸传教士人数、c左岸野人人数、b船状态(左或右)。
开始状态为(3,3,1),目标状态为(0,0,0)。
若需要条件满足,即任何时候,如果野人人数超过传教士人数,那么野人就会把传教士吃掉,要对状态结点的安全性进行判断,判断一个状态是否为安全的,即是否满足在河的任何一岸,传教士人数不少于野人人数,或者只有野人而没有传教士。
传教士野人问题
问题:野人过河问题属于人工智能学科中的一个经典问题,问题描述如下:有三个牧师(也有的翻译为传教士)和三个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于牧师的人数,那么牧师就会有危险. 你能不能找出一种安全的渡河方法呢?解答一:一、算法分析先来看看问题的初始状态和目标状态,假设和分为甲岸和乙岸:初始状态:甲岸,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。
二、基本数据结构仔细阅读问题,可以发现有些基本东西我们必须把握,例如:每时刻河两岸野人牧师各自的数目、船的状态、整个问题状态。
人工智能:野人与修道士问题
野人与修道士问题(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
实验报告课程名称人工智能_____________实验项目野人过河问题_______________实验仪器电脑、visual C++_________系别计算机学院____________专业 __计算机科学与技术_____班级/学号学生姓名 _ __实验日期 2010年月日_______成绩 _______________________指导教师一、实验目的理解并熟悉掌握深度优先搜索和广度优先搜索地方法。
二、实验内容题目:设有3个传教士和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();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个传教士和m个野人来到河边,打算乘一只船从右岸到左岸去。
传教士与野人
实验题目:产生式设计——野人与传教士过河问题专业班级:计算机11-2 学生姓名. 吴璨No. 1137074实验目的:1.掌握人工智能的基础思想2.熟练应用程序实现人工智能3.强化实践能力产生式设计:1.实验语言环境:c语言2.数据结构:typedef struct{int m; //传教士在左岸的实际人数int c; //野人在左岸的实际人数int wz; //为1时船在左岸int sm; //船上传教士的实际人数int sc; //船上野人是实际人数}Baidu;3.算法设计(以一组较小数据为例,假设N=3,K=2)(1)设定状态变量及确定值域。
左岸的传教士数为m,则有m={0,1,2,3};对应右岸的传教士数为3—m;左岸的野人数为c,则有c={0,1,2,3};对应右岸野人数为3—c;左岸船数为b,故又有b={0,1};对应右岸的船数为1-b。
(2)确定状态组,分别列出初始状态集和目标状态集。
问题的状态可以用一个三元数组来描述,以左岸的状态来标记,即右岸的状态可以不必标出。
S k=(m, c, b)初始状态只有一个:S=(3,3,1),初始状态表示全部成员在河的的左岸;目标状态也只有一个:S=(0,0,0),表示全部成员从河的左岸全部渡河完毕。
(3)定义并确定操作集。
以河的左岸为基点来考虑,把船从左岸划向右岸定义为L(Sm,Sc)操作。
其中,第一下标Sm表示船载的传教士数,第二下标Sc表示船载的野人数;同理,从右岸将船划回左岸称之为R(Sm,Sc)操作,下标的定义同前。
(4)估计全部的状态空间数,并尽可能列出全部的状态空间。
在这个问题世界中,S={3,3,1}为初始状态,S=(0,0,0)为目标状态。
全部的可能状态共有32个,如表所示。
值得注意的是按照题目规定的条件,我们应该划去不合法的状态。
例如,首先可以划去岸边野人数目超过传教士的情况,即S4、S8、S9、S20、S24、S25等6种状态是不合法的;其次,应该划去右岸边野人数目超过野人的情况,即S6、S7、S11、S22、S23、S27等情况;余下20种合法状态中,又有4种是不可能出现的状态;S15和S16不可能出现,因为船不可能停靠在无人的岸边;S3不可能出现,因为传教士不可能在数量占优势的野人眼皮底下把船安全地划回来;还应该划去S28,因为传教士也不可能在数量占优势的野人眼皮底下把船安全地划向对岸。
传教士野蛮人过河问题--python
传教⼠野蛮⼈过河问题--python三名传教⼠和三个野蛮⼈同在⼀个⼩河渡⼝,渡⼝上只有⼀条可容两⼈的⼩船。
问题的⽬标是要⽤这条⼩船把这六个⼈全部渡到对岸去,条件是在渡河的过程中,河两岸随时都保持传教⼠⼈数不少于野蛮⼈的⼈数,否则野蛮⼈会把处于少数的传教⼠状态集合为(x,y,b)三元组,x表⽰左岸野⼈数,y表⽰左岸传教⼠数,x,y取值0~3。
b为0表⽰船在左边,b为1表⽰船在右边动作集合为⼀个传教⼠从左到右,两个传教⼠从左到右,⼀个野⼈从左到右,两个野⼈从左到右,⼀个野⼈⼀个传教⼠从左到右;从右到左类似也有5个动作,共10个动作,于是就可以画出⼀个状态转换图,下⾯的python代码可以帮助我们完成这个任state_legal判断给定状态是否合法,act_legal判断在当前状态执⾏给定动作是否合法,f(x,y,b)打印所有从(x,y,b)可以执⾏的动作和转移到的状态def state_legal(x, y, b):if x < 0 or y < 0 or x > 3 or y > 3:return Falseif y < x and y > 0:return Falseelif (3-y) < 3-x and 3-y > 0:return Falseelse:return Truedef act_legal(x, y, b, xx, yy, bb):if b != bb:return Falseif b == 0 and state_legal(x - xx, y - yy, 1 - b):return Trueelif b == 1 and state_legal(x + xx, y + yy, 1 - b):return Trueelse:return False#when calling f, (x,y,b) is ensured to be state_legaldef f(x,y,b):for act in actions:if act_legal(x, y, b, act[0], act[1], act[2]):if act[2] == 0:print(x,y,b,"---",act, '---', x - act[0], y - act[1], 1 - b)else:print(x,y,b,"---",act, '---', x + act[0], y + act[1], 1 - b)a = (0,1,2,3)actions = []for b in (0,1):for x in (0,1,2):for y in (0,1,2):if x + y >= 1 and x + y <= 2:actions.append((x,y,b))print(actions)for x in a:for y in a:for b in (0,1):if not(x == 0 and y == 0) and state_legal(x, y, b):f(x,y,b)#x is num of savages, y is num of missionaries。
传教士与野人
综合设计报告设计名称:人工智能课程设计设计题目:传教士与野人过河问题学生学号:0805030119专业班级:智能1班学生姓名:学生成绩:指导教师(职称):课题工作时间:2010-9-13 至2010-9-25说明:1、报告中的第一、二、三项由指导教师在综合设计开始前填写并发给每个学生;四、五两项(中英文摘要)由学生在完成综合设计后填写。
2、学生成绩由指导教师根据学生的设计情况给出各项分值及总评成绩。
3、指导教师评语一栏由指导教师就学生在整个设计期间的平时表现、设计完成情况、报告的质量及答辩情况,给出客观、全面的评价。
4、所有学生必须参加综合设计的答辩环节,凡不参加答辩者,其成绩一律按不及格处理。
答辩小组成员应由2人及以上教师组成。
5、报告正文字数一般应不少于5000字,也可由指导教师根据本门综合设计的情况另行规定。
6、平时表现成绩低于6分的学生,其综合设计成绩按不及格处理。
7、此表格式为武汉工程大学计算机科学与工程学院提供的基本格式(适用于学院各类综合设计),各教研室可根据本门综合设计的特点及内容做适当的调整,并上报学院批准。
成绩评定表学生姓名:学号:班级:类别合计分值各项分值评分标准实际得分合计得分备注平时表现10 10按时参加综合设计,无旷课、迟到、早退、违反实验室纪律等情况。
完成情况3020按设计任务书的要求完成了全部任务,能完整演示其设计内容,符合要求。
10能对其设计内容进行详细、完整的介绍,并能就指导教师提出的问题进行正确的回答。
报告质量3510报告文字通顺,内容翔实,论述充分、完整,立论正确,结构严谨合理;报告字数符合相关要求,工整规范,整齐划一。
5课题背景介绍清楚,综述分析充分。
5设计方案合理、可行,论证严谨,逻辑性强,具有说服力。
5符号统一;图表完备、符合规范要求。
5能对整个设计过程进行全面的总结,得出有价值的结论或结果。
5参考文献数量在3篇以上,格式符合要求,在正文中正确引用。
python回溯法子集树模板系列——19、野人与传教士问题
python回溯法⼦集树模板系列——19、野⼈与传教⼠问题问题在河的左岸有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, xif 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# 任何时候,船上传教⼠⼈数少于野⼈,或者⽆⼈,或者超载(计算船的合法状态空间时已经考虑到了。
C++实现传教士与野人过河问题实验报告
else operation.push_back(" 0
2 | 右岸->左岸");
currentState.churchL = lastcurrentState.churchL;
currentState.wildL = lastcurrentState.wildL - 2 * 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;//保存当前操作的描述
if (lastcurrentState.boat == lastParameters[i].boat) return 0;
} } //检验人数数据合法性 if (lastcurrentState.churchL < 0 || lastcurrentState.wildL < 0 || lastcurrentState.churchR < 0 || lastcurrentState.wildR < 0)
野人和传教士过河问题的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个野⼈过河.。
人工智能第三版源码-传教士_野人问题
传教士-野人问题有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)规则集合P10 if ( ML ,CL , BL=1 ) then ( ML–1 , CL , BL –1 )P01 if ( ML ,CL , BL=1 ) then ( ML , CL–1 , BL –1 )P11 if ( ML ,CL , BL=1 ) then ( ML–1 , CL–1 , BL –1 )P20 if ( ML ,CL , BL=1 ) then ( ML–2 , CL , BL –1 )P02 if ( ML ,CL , BL=1 ) then ( ML , CL–2 , BL –1 )Q10 if ( ML ,CL , BL=0 ) then ( ML+1 , CL , BL+1 )Q01 if ( ML ,CL , BL=0 ) then ( ML , CL+1 , BL +1 )Q11 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 )Q02 if ( ML ,CL , BL=0 ) then ( ML , CL +2, BL +1 )(3)寻找一个启发式函数引导规则的选用右岸总人数6 – ML – CL 两岸中传教士数目>=野人数目f =–∞其它f=3 Q01 f=2 P02 f=1 Q01 f=1 Q10 f=1 P01 f=2 P11 (3,3,1) (3,2,0) (2,2,0) (3,1,0) (3,2,1) (3,0,0) f=3 P02 (3,1,1) f=2 Q01 (1,1,0) f=4 P20 (2,2,1) f=2 Q11 (1,1,0) f=4 P20 (2,2,1) f=2 Q11 (0,2,0) f=4 P20 (0,3,1) f=3 Q01 (0,1,1) f=5 P02 (0,2,1) f=4 Q01 (0,0,0) f=3 Q01 (1,1,1) f=4 Q10。
用Prolog求解传教士和野人问题
用Prolog求解传教士和野人问题实验七用Prolog求解传教士和野人问题 1、实验目的复习经典谓词演算中的归结原理,掌握人工智能程序设计语言Prolog,理解通过搜索求解问题实现人工智能的思想。
2、实验原理谓词演算中的消解法,3、实验内容设有3个传教士和3个野人同在河的左岸,他们都要到对岸去;河里只有一条船,他们都会划船,但每次渡船至多只能乘两人;如果在任何一边河岸上,野人的数量超过传教士,野人就要吃掉传教士,问怎样才能用船将3个传教士和3个野人从左岸都渡到右岸,又不会发生传教士被吃的事件呢,通过Prolog程序,给出乘船过河的动作序列。
4、实验步骤(1) 设计该问题的状态。
例如:((左岸牧师数,左岸野人数),(右岸牧师数,右岸野人数),船的位置)。
(2) 定义目标状态。
这里是:((0,0),(3,3),1)3) 描述可能的动作。
船上所能够载人的状态就是可能的操作。
用谓词(move表示。
(4) 判断合法状态(5) 深度优先搜索三个传教士和三个野人的示例程序如下:move(1,0).move(0,1).move(0,2).move(2,0).move(1,1).legal((X,Y,_)):-legal1(X),legal1(Y). legal1((X,Y)):-X=:=0,Y>=0,!. legal1((X,Y)):-Y=:=0,X>=0,!. legal1((X,Y)):-X>=Y,X>=0,Y>=0.update((X,Y,0),Move,Statu1):-(A,B)=X,(C,D)=Y,(E,F)=Move,C1 is C+E,D1 is D+F,A1 is A-E,B1 is B-F,Statu1=((A1,B1),(C1,D1),1). update((X,Y,1),Move,Statu1):- (A,B)=X, (C,D)=Y,(E,F)=Move,C1 is C-E,D1 is D-F,A1 is A+E,B1 is B+F,Statu1=((A1,B1),(C1,D1),0). connect(Statu,Statu1):- move(X,Y),update(Statu,(X,Y),Statu1), legal(Statu1).findroad(X,X,L,L):-write(L). findroad(X,Y,L,L1):-connect(X,Z),not(member(Z,L)),findroad(Z,Y,[Z|L],L1).传教士和野人问题有三个牧师和三个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于牧师的人数,那么牧师就会有危险。
人工智能实验——传教士和野人过河C++源程序
ofstream fout(argv[2]);
if(k < 2){//一定无解
fout << "no solution" << endl;
return 0;
}
//初始状态存入结果向量
Node n;
n.x = N;
n.y = N;
n.c = 1;
n0.c = 0;
answer.push_back(n0);
return true;
}
}
Node n0;
n0.x = tx;
n0.y = ty;
n0.c = 0;
answer.push_back(n0);
e[tx+ty*20]=true;
//试探过河,从右岸到左岸
for(j=4;j>=0;j--){
int ttx = tx+Q2[j][0];
if(!crossBy3(N)){
fout << "no solution" << endl;
return 0;
}
}
for(unsigned i=0;i<answer.size();i++){
fout <<"(" << answer.at(i).x <<","<<answer.at(i).y<<","<<answer.at(i).c<<")"<<endl;
人工智能+野人传教士过河问题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个人;
人工智能里野人和传教士问题代码
//而对于函数qq(int& a),这是C++中引入的一个新类型:引用,所带来的新的函数传值方式,即按引用传值。
#include<process.h> /* exit() */#include<stdio.h>#include <stdlib.h>#define NULL 0#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0typedef struct{int m;int c;int b;}QElemType; /* 定义队列的数据元素类型QElemType为结构体类型*/typedef struct _Rule{int m;int c;}Rule;Rule rule[5] = {{1,1}, {1,0}, {0,1}, {2,0}, {0,2}}; // 规则集etypedef struct QNode{QElemType data;struct QNode *next;}QNode,*QueuePtr;typedef struct{QueuePtr front,rear; /* 队头、队尾指针*/}LinkQueue;void InitQueue(LinkQueue *Q){ /* 构造一个空队列Q */(*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode));if(!(*Q).front)exit(0);(*Q).front->next=NULL;}int DeQueue(LinkQueue *Q,QElemType *e){ /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */QueuePtr p;if((*Q).front==(*Q).rear)return ERROR;p=(*Q).front->next;*e=p->data;(*Q).front->next=p->next;if((*Q).rear==p)(*Q).rear=(*Q).front;free(p);return OK;}void EnQueue(LinkQueue *Q,QElemType e){ /* 插入元素e为Q的新的队尾元素*/QueuePtr p=(QueuePtr)malloc(sizeof(QNode));if(!p) /* 存储分配失败*/exit(0);p->data=e;p->next=NULL;(*Q).rear->next=p;(*Q).rear=p;}int cmp(LinkQueue *Q,QElemType e){QueuePtr p=(*Q).front->next;while(p!=NULL){if(p->data.m==e.m&&p->data.c==e.c&&p->data.b==e.b)return TRUE;else p=p->next;}return FALSE;}int QueueEmpty(LinkQueue Q){ /* 若Q为空队列,则返回TRUE,否则返回FALSE */if(Q.front->next==NULL)return TRUE;elsereturn FALSE;}// EnQueue(&q[i],f); /* 将f入队到第i队列(i=0~Qu-1)*/ // DeQueue(&q[i],&customer); /* 删除第i队列的排头客户*/ // if(!QueueEmpty(q[i]))//p=(*Q).front->next;//*e=p->data;void main(){LinkQueue open,closed;QueuePtr p;int i;InitQueue(&open);InitQueue(&closed);QElemType s={3,3,1},e,e1;EnQueue(&open,s);while(!QueueEmpty(open)){DeQueue(&open,&e);EnQueue(&closed,e);if(e.m==0&&e.c==0&&e.b==0){printf("成功!");continue;}for(i=0;i<5;i++){e1.m=e.m,e1.c=e.c,e1.b=e.b;if(e1.b==1)//船在左岸{e1.m=e1.m-rule[i].m;e1.c=e1.c-rule[i].c;e1.b=0;if((e1.m>=e1.c||e1.m==0)&&((3-e1.m)>=(3-e1.c)||(3-e1.m)==0)&&e1.m<=3&&e1.c<=3&&e1.m>=0&&e1.c>=0) {if(!cmp(&closed,e1))if(!cmp(&open,e1))EnQueue(&open,e1);}//需要解决元素问题}//ifelse{e1.m=e1.m+rule[i].m;e1.c=e1.c+rule[i].c;e1.b=1;if((e1.m>=e1.c||e1.m==0)&&((3-e1.m)>=(3-e1.c)||(3-e1.m)==0)&&e1.m<=3&&e1.c<=3&&e1.m>=0&&e1.c>=0) {if(!cmp(&closed,e1))if(!cmp(&open,e1))EnQueue(&open,e1);}//需要解决元素重复问题}//else}//for}//whilep=closed.front;p=p->next;while(p!=NULL){printf("%d,%d,%d\n",p->data.m,p->data.c,p->data.b); p=p->next;}//p=(open).front->next;//e=p->data;//printf("%d",e.m);}。
基于python中networkx包的传教士和野人深度优先搜索算法及可视化实现
基于python中networkx包的传教⼠和野⼈深度优先搜索算法及可视化实现按《⼈⼯智能原理》书上的思路进⾏建模。
只是记录⼀下⾃⼰的作业,感觉之前好多⽤⼼写的代码没利⽤起来,发在博客整理⼀下,不喜勿喷。
在这个问题中,(3,3,1)为初始状态,(0,0,0)为⽬标状态。
全部的可能状态共有32个,如表所⽰, m为左岸传教⼠⼈数, c为左岸野⼈⼈数,b 左岸的船数⽬。
可⽤状态16种,考虑到任何⼀条从S0到达S31的路径都是该问题的解,最短路径共有4条。
图5 m=3,c=3,b=2实验结果图6 m=7,c=6,b=2实验结果从图5上可发现除找出最优路径之外,还有3种同等的最优路径,图 6主要是修改m和c的实验结果拓展,某些情况⽆最短路径⽣成,已经加以限制。
由于b修改会导致先前设定的条件(右岸->左岸之间可去1⼈,右岸->左岸可去2⼈,同时两个可逆)改变,这种情况加⼊判断语句进⾏控制即可,暂时没有进⼀步完善。
本来想传在github上的,好慢。
就先写在这⾥啦~# -*- coding: utf-8 -*-"""Created on Sat Mar 12 18:54:11 2022@author: dobby"""import networkx as nximport matplotlib.pyplot as pltWALKABLE = 'walkable'PARENT = 'parent'VISITED = 'visited'#3维⽹格图def my_graph(m,c,b):plt.subplots(1,1,figsize=(15,7))G=nx.Graph()#若b发⽣变化则以下结点的⽣成规则需要更改G.add_edges_from([((x,y,0), (x,y+1,1))for x in range(m+1)for y in range(c)] + [((x,y,0), (x+1,y,1))for x in range(m)for y in range(c+1)])#右岸->左岸之间可去1⼈G.add_edges_from([((x,y,0), (x+1,y+1,1))for x in range(m)for y in range(c)] + [((x,y,0), (x+2,y,1))for x in range(m-1)for y in range(c+1)] + [((x,y,0), (x,y+2,1))for x in range(m+1)for y in range(c-1)])#右岸->左岸可去2⼈pos = nx.spring_layout(G, iterations=100)nx.draw_networkx(G, pos=pos,font_size=7,font_color='white',node_size=500,width=1)START = (m,c,1)GOAL = (0,0,0)road_closed_nodes = dummy_nodes(G,m,c,b)nx.draw_networkx_nodes(G, pos,nodelist=road_closed_nodes,node_size=500,node_color="red",node_shape="x",label='x')dfs(G, START, GOAL)# 基于栈实深度优先遍历搜索try:path = find_path_by_parent(G, START, GOAL) except:print("该种情况没有可⾏路径")return;print('path', path)nx.draw_networkx_nodes(G, pos,nodelist=path,node_size=400,node_color="green",node_shape='o',)path_edges = []for i in range(len(path)):if (i + 1) == len(path):breakpath_edges.append((path[i], path[i + 1]))print('path_edges', path_edges)G2=G.to_directed()nx.draw_networkx_edges(G2, pos,edgelist=path_edges,width=4,alpha=0.5,edge_color="g")plt.axis('off')plt.show()# 基于栈的深度优先遍历搜索def dfs(G, START, GOAL):for n in G.nodes():G.nodes[n]['visited'] = False#初始所有点都是未被访问的stack = [] # ⽤列表当作⼀个栈,只在栈顶操作(数组的第1个位置)stack.append(START)close_list = []while True:if len(stack) == 0:breakprint('-----')print('stack-', stack)visit_node = stack[0]G.nodes[visit_node]['visited'] = Trueprint('访问', visit_node)if visit_node == GOAL:breakclose_list.append(visit_node)#已访问的节点count = 0neighbors = nx.neighbors(G, visit_node)#寻找visit_node周围的结点for node in neighbors:#依次遍历visit_node周围的节点visited = G.nodes[node][VISITED]try:walkable = G.nodes[node][WALKABLE]#如果存在之前设定的WALKABLE则为阻碍点except:walkable = Trueif (visited) or (node in stack) or (node in close_list) or (not walkable):continue#如果结点被访问,或者在将要访问的stack中,或者在已被记录的最短路径close_list中,或者是阻碍点则跳过 G.nodes[node][PARENT] = visit_node#设定该找到的节点node的⽗节点为visit_node,改变Gstack.append(node)#将node压⼊stackcount = count + 1#计数if count == 0:#该节点下没有节点被压⼊print(visit_node, '尽头')del (stack[0])print('弹出', visit_node)print('stack--', stack)#显⽰进⼊下次循环的stackreturn stackdef find_path_by_parent(G, START, GOAL):t = GOALpath = [t]is_find = Falsewhile not is_find:for n in G.nodes(data=True):#G.nodes第⼀个是结点的数据,第⼆个是字典存储的结点属性if n[0] == t:parent = n[1][PARENT]#找Node中parent属性存储的信息path.append(parent)if parent == START:#找到开始结点is_find = Truebreakt = parentpath.reverse()#从GOAL->START需要翻转return pathdef dummy_nodes(G,m,c,b):list1=[];#list1.append((m,c,0))#去右岸时,船未携带⼈不需要考虑本不在⽣成点中#list1.append((0,0,1))#左岸⽆⼈却有船不需要考虑本不在⽣成点中for i in range(m+1):for j in range(c+1):if(i<j and i!=0):#左岸野⼈会袭击传教⼠的情况p=(i,j,0)q=(i,j,1)list1.append(p)list1.append(q)if(m-i<c-j and m-i!=0):#右岸野⼈会袭击传教⼠的情况p=(i,j,0)q=(i,j,1)list1.append(p)list1.append(q)for i in list1:G.nodes[i][WALKABLE] = False return list1if__name__ == '__main__':m=3#⾃定义修道⼠数c=3#⾃定义野⼈数b=2my_graph(m,c,b)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
//而对于函数qq(int& a),这是C++中引入的一个新类型:引用,所带来的新的函数传值方式,即按引用传值。
#include<process.h> /* exit() */
#include<stdio.h>
#include <stdlib.h>
#define NULL 0
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
typedef struct
{
int m;
int c;
int b;
}QElemType; /* 定义队列的数据元素类型QElemType为结构体类型*/
typedef struct _Rule
{
int m;
int c;
}Rule;
Rule rule[5] = {{1,1}, {1,0}, {0,1}, {2,0}, {0,2}}; // 规则集e
typedef struct QNode
{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front,rear; /* 队头、队尾指针*/
}LinkQueue;
void InitQueue(LinkQueue *Q)
{ /* 构造一个空队列Q */
(*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode));
if(!(*Q).front)
exit(0);
(*Q).front->next=NULL;
}
int DeQueue(LinkQueue *Q,QElemType *e)
{ /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */
QueuePtr p;
if((*Q).front==(*Q).rear)
return ERROR;
p=(*Q).front->next;
*e=p->data;
(*Q).front->next=p->next;
if((*Q).rear==p)
(*Q).rear=(*Q).front;
free(p);
return OK;
}
void EnQueue(LinkQueue *Q,QElemType e)
{ /* 插入元素e为Q的新的队尾元素*/
QueuePtr p=(QueuePtr)malloc(sizeof(QNode));
if(!p) /* 存储分配失败*/
exit(0);
p->data=e;
p->next=NULL;
(*Q).rear->next=p;
(*Q).rear=p;
}
int cmp(LinkQueue *Q,QElemType e){
QueuePtr p=(*Q).front->next;
while(p!=NULL){
if(p->data.m==e.m&&p->data.c==e.c&&p->data.b==e.b)
return TRUE;
else p=p->next;
}
return FALSE;
}
int QueueEmpty(LinkQueue Q)
{ /* 若Q为空队列,则返回TRUE,否则返回FALSE */
if(Q.front->next==NULL)
return TRUE;
else
return FALSE;
}
// EnQueue(&q[i],f); /* 将f入队到第i队列(i=0~Qu-1)*/ // DeQueue(&q[i],&customer); /* 删除第i队列的排头客户*/ // if(!QueueEmpty(q[i]))
//p=(*Q).front->next;
//*e=p->data;
void main(){
LinkQueue open,closed;
QueuePtr p;
int i;
InitQueue(&open);
InitQueue(&closed);
QElemType s={3,3,1},e,e1;
EnQueue(&open,s);
while(!QueueEmpty(open)){
DeQueue(&open,&e);
EnQueue(&closed,e);
if(e.m==0&&e.c==0&&e.b==0)
{printf("成功!");
continue;}
for(i=0;i<5;i++)
{e1.m=e.m,e1.c=e.c,e1.b=e.b;
if(e1.b==1)//船在左岸
{
e1.m=e1.m-rule[i].m;
e1.c=e1.c-rule[i].c;
e1.b=0;
if((e1.m>=e1.c||e1.m==0)&&((3-e1.m)>=(3-e1.c)||(3-e1.m)==0)&&e1.m<=3&&e1.c<=3&&e1.m>=0&&e1.c>=0) {if(!cmp(&closed,e1))
if(!cmp(&open,e1))
EnQueue(&open,e1);}//需要解决元素问题
}//if
else
{e1.m=e1.m+rule[i].m;
e1.c=e1.c+rule[i].c;
e1.b=1;
if((e1.m>=e1.c||e1.m==0)&&((3-e1.m)>=(3-e1.c)||(3-
e1.m)==0)&&e1.m<=3&&e1.c<=3&&e1.m>=0&&e1.c>=0) {if(!cmp(&closed,e1))
if(!cmp(&open,e1))
EnQueue(&open,e1);}//需要解决元素重复问题
}//else
}//for
}//while
p=closed.front;
p=p->next;
while(p!=NULL){
printf("%d,%d,%d\n",p->data.m,p->data.c,p->data.b); p=p->next;
}
//p=(open).front->next;
//e=p->data;
//printf("%d",e.m);
}。